@ai-matrx/content-ir 0.10.3 → 0.11.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 CHANGED
@@ -1,5 +1,62 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.0 — 2026-09-08
4
+
5
+ **Kind Directives move into the kernel — `/directives`.** A directive
6
+ (`{"__kind": "directive_v1_<class>_<noun>", "items": [...]}`) is a kind
7
+ instance, and the grammar that recognises one lived only in matrx-frontend
8
+ (`features/content-ir/directives/`). Workflow Studio had no copy, so the agent
9
+ builder's envelope streamed into the Plan Room as raw text while the studio's
10
+ resolver 404'd on the slug. The whole pure half now ships here, ported
11
+ verbatim from the aidream source of record
12
+ (`matrx_graph/content_ir/directives.py`):
13
+
14
+ - `directives/grammar.ts` — `RESERVED_PREFIX`, the CLOSED class vocabulary,
15
+ `CAPABILITY_BY_CLASS`, `buildDirectiveSlug` / `parseDirectiveSlug` /
16
+ `isReservedDirectiveSlug`, THE POSITION LAW (`executesAtOutputRoot`,
17
+ `resolvesInContent`), `isKindDirective` / `directiveSlugOf`,
18
+ `buildKindDirective`, and `looksLikeDirectiveHead` (mid-stream recognition).
19
+ - `directives/decode.ts` — `decodeDirective` / `tryDecodeDirective` /
20
+ `tryDecodeDirectiveContent` (JSON text or a parsed value), `DecodedDirective`,
21
+ `DirectiveDecodeError`.
22
+ - `directives/legacy-shell.ts` — THE ONE read-only shim for the retired 4-key
23
+ shell, reachable only through the decoder; its use counter lives on a
24
+ `globalThis` `Symbol.for` slot so the root and `./directives` bundles count
25
+ the same uses (the tarball canary proves it).
26
+ - `directives/display.ts` — the auto-view naming (`directiveDisplay`,
27
+ `nounLabel`, `nounFamily`, `nounTitleColumn`) over an injectable
28
+ `DirectiveNounCatalog`; degrades to a title-cased token, never a slug.
29
+ - `directives/item-summary.ts` — `itemTitle` / `itemSubtitle` / `itemFacts`
30
+ (scalars only, THE UUID RULE).
31
+ - `directives/item-kind.ts` — THE DIRECTIVE⇄KIND SEAM:
32
+ `directiveItemKindFromEdges` (reads the `items` edge of a directive
33
+ KindDescriptor — the ONE kind endpoint serves every directive shape since
34
+ aidream 2026-09-08) and `asKindInstance` (`__kind` FIRST, never overwritten).
35
+
36
+ Exported from the root and from the new `./directives` subpath.
37
+
38
+ ### Consumer action
39
+
40
+ - **matrx-frontend**: delete `features/content-ir/directives/{grammar,decode,
41
+ legacyShell,itemKind,itemSummary,nounDisplay}.ts` and import the same names
42
+ from `@ai-matrx/content-ir` (`itemTitle` now takes the title COLUMN, not the
43
+ noun; `directiveDisplay`/`nounLabel`/`nounFamily`/`nounTitleColumn` take an
44
+ optional catalog lookup; `asKindInstance(item, kind)` takes the resolved
45
+ kind). Retire `scripts/check-legacy-shim-containment.ts` (the shim is
46
+ package-internal) and repoint `sync-directive-grammar` at the package.
47
+ - **Workflow Studio / dashboard**: nothing to delete (no copy existed).
48
+
49
+ ## 0.10.4
50
+
51
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
52
+ `git diff npm/content-ir-core/v0.10.3..npm/content-ir-core/v0.10.4 -- apps/shared/content-ir-core`).
53
+ No source changes intended and no consumer action required.
54
+
55
+ ## 0.10.1
56
+
57
+ Automatic changed-only republish (docs/metadata drift since v0.10.0; dist verified
58
+ byte-identical to v0.10.0). No source changes and no consumer action required.
59
+
3
60
  ## 0.10.3 — 2026-08-31
4
61
 
5
62
  **Bug fix — inline objects nest to any depth, on the streaming path too.**
@@ -0,0 +1,386 @@
1
+ 'use strict';
2
+
3
+ // core/kind-schema.types.ts
4
+ var KIND_KEY = "__kind";
5
+
6
+ // directives/grammar.ts
7
+ var RESERVED_PREFIX = "directive_v";
8
+ var DIRECTIVE_VERSION = 1;
9
+ var SLUG_PREFIX = `${RESERVED_PREFIX}${DIRECTIVE_VERSION}_`;
10
+ var CLASSES = [
11
+ "reference",
12
+ "view",
13
+ "create",
14
+ "update",
15
+ "delete",
16
+ "action",
17
+ "validation",
18
+ "secret"
19
+ ];
20
+ var CAPABILITY_BY_CLASS = {
21
+ reference: "pure",
22
+ view: "pure",
23
+ validation: "pure",
24
+ secret: "sensitive",
25
+ create: "side_effect",
26
+ update: "side_effect",
27
+ delete: "side_effect",
28
+ action: "side_effect"
29
+ };
30
+ var SIDE_EFFECT_CLASSES = new Set(
31
+ CLASSES.filter((c) => CAPABILITY_BY_CLASS[c] === "side_effect")
32
+ );
33
+ var IN_CONTENT_CLASSES = /* @__PURE__ */ new Set([
34
+ "reference",
35
+ "secret"
36
+ ]);
37
+ function isDirectiveClass(value) {
38
+ return typeof value === "string" && Object.prototype.hasOwnProperty.call(CAPABILITY_BY_CLASS, value);
39
+ }
40
+ function isReservedDirectiveSlug(slug) {
41
+ return typeof slug === "string" && slug.startsWith(RESERVED_PREFIX);
42
+ }
43
+ function isToken(value) {
44
+ return /^[a-z][a-z0-9_]*$/.test(value);
45
+ }
46
+ function buildDirectiveSlug(directiveClass, noun, version = DIRECTIVE_VERSION) {
47
+ if (!isDirectiveClass(directiveClass)) {
48
+ throw new Error(
49
+ `unknown directive class ${JSON.stringify(directiveClass)}; the vocabulary is CLOSED: ${CLASSES.join(", ")}.`
50
+ );
51
+ }
52
+ if (typeof noun !== "string" || !isToken(noun)) {
53
+ throw new Error(
54
+ `invalid directive noun ${JSON.stringify(noun)} for class ${JSON.stringify(directiveClass)}: a noun is lowercase [a-z0-9_], starts with a letter, and is non-empty.`
55
+ );
56
+ }
57
+ return `${RESERVED_PREFIX}${version}_${directiveClass}_${noun}`;
58
+ }
59
+ function parseDirectiveSlug(slug) {
60
+ if (!isReservedDirectiveSlug(slug)) return null;
61
+ const rest = slug.slice(RESERVED_PREFIX.length);
62
+ const firstSep = rest.indexOf("_");
63
+ if (firstSep <= 0) return null;
64
+ const versionDigits = rest.slice(0, firstSep);
65
+ if (!/^[0-9]+$/.test(versionDigits)) return null;
66
+ const remainder = rest.slice(firstSep + 1);
67
+ const classSep = remainder.indexOf("_");
68
+ if (classSep <= 0) return null;
69
+ const directiveClass = remainder.slice(0, classSep);
70
+ const noun = remainder.slice(classSep + 1);
71
+ if (!isDirectiveClass(directiveClass) || !isToken(noun)) return null;
72
+ return {
73
+ slug,
74
+ version: Number.parseInt(versionDigits, 10),
75
+ directiveClass,
76
+ noun,
77
+ capability: CAPABILITY_BY_CLASS[directiveClass],
78
+ executes: executesAtOutputRoot(directiveClass),
79
+ inContent: resolvesInContent(directiveClass)
80
+ };
81
+ }
82
+ function capabilityOf(directiveClass) {
83
+ return CAPABILITY_BY_CLASS[directiveClass];
84
+ }
85
+ function executesAtOutputRoot(directiveClass) {
86
+ return isDirectiveClass(directiveClass) && SIDE_EFFECT_CLASSES.has(directiveClass);
87
+ }
88
+ function resolvesInContent(directiveClass) {
89
+ return isDirectiveClass(directiveClass) && IN_CONTENT_CLASSES.has(directiveClass);
90
+ }
91
+ function directiveSlugOf(obj) {
92
+ if (typeof obj !== "object" || obj === null || Array.isArray(obj)) return null;
93
+ const slug = obj[KIND_KEY];
94
+ return isReservedDirectiveSlug(slug) ? slug : null;
95
+ }
96
+ function isKindDirective(obj) {
97
+ return directiveSlugOf(obj) !== null;
98
+ }
99
+ function buildKindDirective(slug, items) {
100
+ return { [KIND_KEY]: slug, items };
101
+ }
102
+ function looksLikeDirectiveHead(content) {
103
+ const match = content.trimStart().match(/^\{\s*"__kind"\s*:\s*"([^"]*)/);
104
+ return !!match && isReservedDirectiveSlug(match[1]);
105
+ }
106
+
107
+ // directives/legacy-shell.ts
108
+ var LEGACY_SENTINEL = "matrx_version";
109
+ var CLASS_BY_LEGACY_KIND = {
110
+ reference: "reference",
111
+ secret: "secret",
112
+ validation: "validation"
113
+ };
114
+ var LEGACY_SIDE_EFFECT_KINDS = /* @__PURE__ */ new Set(["output_directive", "function"]);
115
+ var VERB_NOUN_RE = /^(create|update|delete):([a-z][a-z0-9_]*)$/;
116
+ var USES_SLOT = /* @__PURE__ */ Symbol.for("ai-matrx.content-ir.legacy-shell-uses");
117
+ var uses = globalThis[USES_SLOT] ??= { count: 0 };
118
+ function legacyShellUses() {
119
+ return uses.count;
120
+ }
121
+ function resetLegacyShellUses() {
122
+ uses.count = 0;
123
+ }
124
+ function isLegacyShell(obj) {
125
+ if (typeof obj !== "object" || obj === null || Array.isArray(obj)) return false;
126
+ const record = obj;
127
+ if (!(LEGACY_SENTINEL in record)) return false;
128
+ const kind = record.kind;
129
+ return typeof kind === "string" && (kind in CLASS_BY_LEGACY_KIND || LEGACY_SIDE_EFFECT_KINDS.has(kind));
130
+ }
131
+ function slugForLegacy(kind, type) {
132
+ let directiveClass;
133
+ let noun;
134
+ if (LEGACY_SIDE_EFFECT_KINDS.has(kind)) {
135
+ const match = VERB_NOUN_RE.exec(type);
136
+ if (match) {
137
+ directiveClass = match[1];
138
+ noun = match[2];
139
+ } else {
140
+ directiveClass = "action";
141
+ noun = type;
142
+ }
143
+ } else {
144
+ const mapped = CLASS_BY_LEGACY_KIND[kind];
145
+ if (!mapped) return null;
146
+ directiveClass = mapped;
147
+ noun = type;
148
+ }
149
+ try {
150
+ return buildDirectiveSlug(directiveClass, noun);
151
+ } catch {
152
+ return null;
153
+ }
154
+ }
155
+ function translateLegacyShell(obj) {
156
+ const kind = obj.kind;
157
+ const type = obj.type;
158
+ if (typeof kind !== "string" || typeof type !== "string") return null;
159
+ const slug = slugForLegacy(kind, type);
160
+ if (slug === null) return null;
161
+ const items = obj.items;
162
+ uses.count += 1;
163
+ return { [KIND_KEY]: slug, items: Array.isArray(items) ? [...items] : [] };
164
+ }
165
+
166
+ // directives/decode.ts
167
+ var DirectiveDecodeError = class extends Error {
168
+ constructor(message) {
169
+ super(message);
170
+ this.name = "DirectiveDecodeError";
171
+ }
172
+ };
173
+ function asObject(value) {
174
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
175
+ return value;
176
+ }
177
+ function decodeDirective(value) {
178
+ let obj = asObject(value);
179
+ if (obj === null) return null;
180
+ let legacy = false;
181
+ if (isLegacyShell(obj)) {
182
+ const translated = translateLegacyShell(obj);
183
+ if (translated === null) {
184
+ throw new DirectiveDecodeError(
185
+ `a retired 4-key shell with kind=${JSON.stringify(obj.kind)} type=${JSON.stringify(obj.type)} does not map onto the Kind Directives grammar. Emit the current shell: {"${KIND_KEY}": "directive_v1_<class>_<noun>", "items": [...]}.`
186
+ );
187
+ }
188
+ obj = translated;
189
+ legacy = true;
190
+ }
191
+ const rawSlug = obj[KIND_KEY];
192
+ if (!isReservedDirectiveSlug(rawSlug)) return null;
193
+ const parsed = parseDirectiveSlug(rawSlug);
194
+ if (parsed === null) {
195
+ throw new DirectiveDecodeError(
196
+ `malformed directive slug ${JSON.stringify(rawSlug)} \u2014 it claims the reserved "directive_v" namespace but does not parse as directive_v<version>_<class>_<noun>.`
197
+ );
198
+ }
199
+ const rawItems = obj.items;
200
+ const items = Array.isArray(rawItems) ? rawItems.filter((i) => asObject(i) !== null) : [];
201
+ return {
202
+ parsed,
203
+ slug: parsed.slug,
204
+ directiveClass: parsed.directiveClass,
205
+ noun: parsed.noun,
206
+ items,
207
+ shell: { [KIND_KEY]: parsed.slug, items },
208
+ legacyShell: legacy
209
+ };
210
+ }
211
+ function tryDecodeDirective(value, onError) {
212
+ try {
213
+ return decodeDirective(value);
214
+ } catch (error) {
215
+ onError?.(error instanceof Error ? error.message : "directive decode failed");
216
+ return null;
217
+ }
218
+ }
219
+ function tryDecodeDirectiveContent(content, onError) {
220
+ if (typeof content !== "string") return tryDecodeDirective(content, onError);
221
+ let parsed;
222
+ try {
223
+ parsed = JSON.parse(content);
224
+ } catch {
225
+ return null;
226
+ }
227
+ return tryDecodeDirective(parsed, onError);
228
+ }
229
+
230
+ // directives/display.ts
231
+ function titleCaseToken(token) {
232
+ const words = token.replace(/_/g, " ").trim();
233
+ return words ? words.charAt(0).toUpperCase() + words.slice(1) : token;
234
+ }
235
+ var ACTION_BY_CLASS = {
236
+ reference: "Reference",
237
+ view: "View",
238
+ create: "Create",
239
+ update: "Update",
240
+ delete: "Delete",
241
+ action: "Run",
242
+ validation: "Validate",
243
+ secret: "Secret"
244
+ };
245
+ function nounLabel(noun, catalog) {
246
+ const label = catalog?.(noun)?.label;
247
+ return label && label.length > 0 ? label : titleCaseToken(noun);
248
+ }
249
+ function nounFamily(noun, catalog) {
250
+ return catalog?.(noun)?.family ?? "";
251
+ }
252
+ function nounTitleColumn(noun, catalog) {
253
+ return catalog?.(noun)?.titleColumn ?? null;
254
+ }
255
+ function directiveDisplay(directiveClass, noun, catalog) {
256
+ const label = nounLabel(noun, catalog);
257
+ const action = ACTION_BY_CLASS[directiveClass];
258
+ return {
259
+ noun: label,
260
+ family: nounFamily(noun, catalog),
261
+ action,
262
+ title: `${action} ${label}`
263
+ };
264
+ }
265
+
266
+ // directives/item-summary.ts
267
+ var NAME_KEYS = ["name", "title", "label", "heading", "slug", "key", "question", "summary"];
268
+ var FACT_EXCLUDE = /* @__PURE__ */ new Set([
269
+ "__kind",
270
+ ...NAME_KEYS,
271
+ "id",
272
+ "description",
273
+ "about",
274
+ "notes",
275
+ "content",
276
+ "text",
277
+ "body",
278
+ "organization_id",
279
+ "user_id",
280
+ "created_by",
281
+ "resource_type"
282
+ ]);
283
+ function firstString(item, keys) {
284
+ for (const key of keys) {
285
+ const value = item[key];
286
+ if (typeof value === "string" && value.trim()) return value.trim();
287
+ }
288
+ return null;
289
+ }
290
+ function itemTitle(item, titleColumn, index, total) {
291
+ const fromCatalog = titleColumn ? firstString(item, [titleColumn]) : null;
292
+ const name = fromCatalog ?? firstString(item, NAME_KEYS);
293
+ if (name) return name;
294
+ return total > 1 ? `Item ${index + 1} of ${total}` : "Item";
295
+ }
296
+ function itemSubtitle(item) {
297
+ return firstString(item, ["description", "about", "summary", "doc"]);
298
+ }
299
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
300
+ var FACT_LABEL_OVERRIDES = {
301
+ variable_definitions: "variables",
302
+ context_policies: "context",
303
+ custom_tools: "custom tools"
304
+ };
305
+ function factLabel(key) {
306
+ return FACT_LABEL_OVERRIDES[key] ?? key.replace(/_/g, " ");
307
+ }
308
+ function itemFacts(item, limit = 4) {
309
+ const facts = [];
310
+ for (const [key, value] of Object.entries(item)) {
311
+ if (facts.length >= limit) break;
312
+ if (FACT_EXCLUDE.has(key)) continue;
313
+ if (Array.isArray(value)) {
314
+ if (value.length === 0) continue;
315
+ facts.push({ key, label: factLabel(key), value: String(value.length) });
316
+ continue;
317
+ }
318
+ if (typeof value === "string") {
319
+ const trimmed = value.trim();
320
+ if (!trimmed || trimmed.length > 40) continue;
321
+ if (UUID_RE.test(trimmed)) continue;
322
+ facts.push({ key, label: factLabel(key), value: trimmed });
323
+ continue;
324
+ }
325
+ if (typeof value === "number" || typeof value === "boolean") {
326
+ facts.push({ key, label: factLabel(key), value: String(value) });
327
+ }
328
+ }
329
+ return facts;
330
+ }
331
+
332
+ // directives/item-kind.ts
333
+ function directiveItemKindFromEdges(edges) {
334
+ for (const edge of edges ?? []) {
335
+ const field = edge.field_name ?? edge.fieldPath;
336
+ const child = edge.child_kind ?? edge.childKind;
337
+ if (field === "items" && typeof child === "string" && child) return child;
338
+ }
339
+ return null;
340
+ }
341
+ function asKindInstance(item, kind) {
342
+ const existing = item[KIND_KEY];
343
+ const resolved = typeof existing === "string" && existing ? existing : kind;
344
+ if (!resolved) return null;
345
+ return { [KIND_KEY]: resolved, ...item };
346
+ }
347
+
348
+ exports.ACTION_BY_CLASS = ACTION_BY_CLASS;
349
+ exports.CAPABILITY_BY_CLASS = CAPABILITY_BY_CLASS;
350
+ exports.CLASSES = CLASSES;
351
+ exports.DIRECTIVE_VERSION = DIRECTIVE_VERSION;
352
+ exports.DirectiveDecodeError = DirectiveDecodeError;
353
+ exports.IN_CONTENT_CLASSES = IN_CONTENT_CLASSES;
354
+ exports.KIND_KEY = KIND_KEY;
355
+ exports.RESERVED_PREFIX = RESERVED_PREFIX;
356
+ exports.SIDE_EFFECT_CLASSES = SIDE_EFFECT_CLASSES;
357
+ exports.SLUG_PREFIX = SLUG_PREFIX;
358
+ exports.asKindInstance = asKindInstance;
359
+ exports.buildDirectiveSlug = buildDirectiveSlug;
360
+ exports.buildKindDirective = buildKindDirective;
361
+ exports.capabilityOf = capabilityOf;
362
+ exports.decodeDirective = decodeDirective;
363
+ exports.directiveDisplay = directiveDisplay;
364
+ exports.directiveItemKindFromEdges = directiveItemKindFromEdges;
365
+ exports.directiveSlugOf = directiveSlugOf;
366
+ exports.executesAtOutputRoot = executesAtOutputRoot;
367
+ exports.isDirectiveClass = isDirectiveClass;
368
+ exports.isKindDirective = isKindDirective;
369
+ exports.isLegacyShell = isLegacyShell;
370
+ exports.isReservedDirectiveSlug = isReservedDirectiveSlug;
371
+ exports.itemFacts = itemFacts;
372
+ exports.itemSubtitle = itemSubtitle;
373
+ exports.itemTitle = itemTitle;
374
+ exports.legacyShellUses = legacyShellUses;
375
+ exports.looksLikeDirectiveHead = looksLikeDirectiveHead;
376
+ exports.nounFamily = nounFamily;
377
+ exports.nounLabel = nounLabel;
378
+ exports.nounTitleColumn = nounTitleColumn;
379
+ exports.parseDirectiveSlug = parseDirectiveSlug;
380
+ exports.resetLegacyShellUses = resetLegacyShellUses;
381
+ exports.resolvesInContent = resolvesInContent;
382
+ exports.titleCaseToken = titleCaseToken;
383
+ exports.tryDecodeDirective = tryDecodeDirective;
384
+ exports.tryDecodeDirectiveContent = tryDecodeDirectiveContent;
385
+ //# sourceMappingURL=directives.cjs.map
386
+ //# sourceMappingURL=directives.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../core/kind-schema.types.ts","../directives/grammar.ts","../directives/legacy-shell.ts","../directives/decode.ts","../directives/display.ts","../directives/item-summary.ts","../directives/item-kind.ts"],"names":[],"mappings":"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","file":"directives.cjs","sourcesContent":["/**\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 * Kind Directives — the grammar, the shell, and the position law (kernel edition).\n *\n * ONE system (Arman, 2026-08-23): the Matrx Envelope/Directive protocol and the\n * Content IR kind system are one system. A directive is an ordinary kind\n * instance — `{ \"__kind\": \"directive_v1_<class>_<noun>\", \"items\": [...] }` —\n * whose registered shape additionally carries execution semantics on the\n * server. This module is the PURE half, ported verbatim from the aidream source\n * of record (`packages/matrx-graph/matrx_graph/content_ir/directives.py`) so\n * every UI parses the grammar identically. It lives in the KERNEL because a\n * host that can parse a kind must be able to recognise a directive without a\n * second copy of these rules (matrx-frontend carried the only copy until\n * 2026-09-08; Workflow Studio had none and rendered directives as raw text).\n *\n * THE SLUG GRAMMAR — `directive_v<version>_<class>_<noun>`:\n * - `directive_v` is a RESERVED prefix; a hand-authored kind may never claim it.\n * - `<class>` comes from a CLOSED vocabulary, so parsing is unambiguous even\n * though nouns contain underscores: `directive_v1_reference_create_task` is\n * `(reference, \"create_task\")`.\n * - capability is DERIVED from the class, never stored twice.\n */\n\nimport { KIND_KEY } from \"../core/kind-schema.types\";\n\nexport { KIND_KEY };\n\n/** The reserved slug prefix. ANY kind slug starting with this belongs to the Kind Directives protocol. */\nexport const RESERVED_PREFIX = \"directive_v\" as const;\n\n/** Current directive grammar version. */\nexport const DIRECTIVE_VERSION = 1 as const;\n\n/** The full prefix of a v1 directive slug. */\nexport const SLUG_PREFIX = `${RESERVED_PREFIX}${DIRECTIVE_VERSION}_` as const;\n\n/** The CLOSED class vocabulary. Closed is what makes the grammar parseable. */\nexport const CLASSES = [\n \"reference\",\n \"view\",\n \"create\",\n \"update\",\n \"delete\",\n \"action\",\n \"validation\",\n \"secret\",\n] as const;\n\nexport type DirectiveClass = (typeof CLASSES)[number];\n\nexport type DirectiveCapability = \"pure\" | \"sensitive\" | \"side_effect\";\n\n/** class → capability. DERIVED, never stored on a shape. */\nexport const CAPABILITY_BY_CLASS: Readonly<Record<DirectiveClass, DirectiveCapability>> = {\n reference: \"pure\",\n view: \"pure\",\n validation: \"pure\",\n secret: \"sensitive\",\n create: \"side_effect\",\n update: \"side_effect\",\n delete: \"side_effect\",\n action: \"side_effect\",\n};\n\n/** The classes that EXECUTE at an agent's output root — a durable side effect. */\nexport const SIDE_EFFECT_CLASSES: ReadonlySet<DirectiveClass> = new Set(\n CLASSES.filter((c) => CAPABILITY_BY_CLASS[c] === \"side_effect\"),\n);\n\n/**\n * The classes that resolve to a LIVE VALUE inside content. STRICT BY CHOICE,\n * mirroring the server: exactly `reference` + `secret`.\n */\nexport const IN_CONTENT_CLASSES: ReadonlySet<DirectiveClass> = new Set<DirectiveClass>([\n \"reference\",\n \"secret\",\n]);\n\n/** A parsed directive slug. `slug` round-trips through `buildDirectiveSlug`. */\nexport interface DirectiveSlug {\n slug: string;\n version: number;\n directiveClass: DirectiveClass;\n noun: string;\n capability: DirectiveCapability;\n /** Executes at an agent's output root (THE position law, half one). */\n executes: boolean;\n /** Resolves to a live value inside content (THE position law, half two). */\n inContent: boolean;\n}\n\nexport function isDirectiveClass(value: unknown): value is DirectiveClass {\n return (\n typeof value === \"string\" &&\n Object.prototype.hasOwnProperty.call(CAPABILITY_BY_CLASS, value)\n );\n}\n\n/**\n * Whether `slug` sits in the reserved Kind Directives namespace. Deliberately\n * broader than {@link parseDirectiveSlug}: a MALFORMED `directive_v…` slug is\n * still reserved, so authoring gates reject it instead of letting a near-miss\n * through as an ordinary kind.\n */\nexport function isReservedDirectiveSlug(slug: unknown): slug is string {\n return typeof slug === \"string\" && slug.startsWith(RESERVED_PREFIX);\n}\n\n/** A noun/token: starts with a lowercase letter, then `[a-z0-9_]`. */\nfunction isToken(value: string): boolean {\n return /^[a-z][a-z0-9_]*$/.test(value);\n}\n\n/**\n * `(\"create\", \"task\") → \"directive_v1_create_task\"`. THROWS on a class outside\n * the closed vocabulary or an ill-formed noun — a slug that cannot be parsed\n * back must never be mintable.\n */\nexport function buildDirectiveSlug(\n directiveClass: string,\n noun: string,\n version: number = DIRECTIVE_VERSION,\n): string {\n if (!isDirectiveClass(directiveClass)) {\n throw new Error(\n `unknown directive class ${JSON.stringify(directiveClass)}; the vocabulary is CLOSED: ${CLASSES.join(\", \")}.`,\n );\n }\n if (typeof noun !== \"string\" || !isToken(noun)) {\n throw new Error(\n `invalid directive noun ${JSON.stringify(noun)} for class ${JSON.stringify(directiveClass)}: a noun is lowercase [a-z0-9_], starts with a letter, and is non-empty.`,\n );\n }\n return `${RESERVED_PREFIX}${version}_${directiveClass}_${noun}`;\n}\n\n/**\n * Parse a directive slug, or `null` when `slug` is not one. A slug that IS in\n * the reserved namespace but does not parse returns `null` too — pair with\n * {@link isReservedDirectiveSlug} to tell \"ordinary kind\" from \"malformed\n * directive\"; every such caller treats the malformed case as an ERROR.\n */\nexport function parseDirectiveSlug(slug: unknown): DirectiveSlug | null {\n if (!isReservedDirectiveSlug(slug)) return null;\n const rest = slug.slice(RESERVED_PREFIX.length);\n const firstSep = rest.indexOf(\"_\");\n if (firstSep <= 0) return null;\n const versionDigits = rest.slice(0, firstSep);\n if (!/^[0-9]+$/.test(versionDigits)) return null;\n const remainder = rest.slice(firstSep + 1);\n const classSep = remainder.indexOf(\"_\");\n if (classSep <= 0) return null;\n const directiveClass = remainder.slice(0, classSep);\n const noun = remainder.slice(classSep + 1);\n if (!isDirectiveClass(directiveClass) || !isToken(noun)) return null;\n return {\n slug,\n version: Number.parseInt(versionDigits, 10),\n directiveClass,\n noun,\n capability: CAPABILITY_BY_CLASS[directiveClass],\n executes: executesAtOutputRoot(directiveClass),\n inContent: resolvesInContent(directiveClass),\n };\n}\n\nexport function capabilityOf(directiveClass: DirectiveClass): DirectiveCapability {\n return CAPABILITY_BY_CLASS[directiveClass];\n}\n\n/** THE position law, half one: only a side-effect class executes at an agent's output root. */\nexport function executesAtOutputRoot(directiveClass: string): boolean {\n return isDirectiveClass(directiveClass) && SIDE_EFFECT_CLASSES.has(directiveClass);\n}\n\n/** THE position law, half two: only a pointer or a sensitive value resolves to a live value inside content. */\nexport function resolvesInContent(directiveClass: string): boolean {\n return isDirectiveClass(directiveClass) && IN_CONTENT_CLASSES.has(directiveClass);\n}\n\n/**\n * The `__kind` of `obj` when it is in the reserved namespace, else null. Reads\n * the RESERVED namespace, not the parsed grammar, so a malformed directive is\n * still recognised as a directive (and rejected downstream with a real message).\n */\nexport function directiveSlugOf(obj: unknown): string | null {\n if (typeof obj !== \"object\" || obj === null || Array.isArray(obj)) return null;\n const slug = (obj as Record<string, unknown>)[KIND_KEY];\n return isReservedDirectiveSlug(slug) ? slug : null;\n}\n\n/** THE detector — a dict whose `__kind` is in the reserved namespace. */\nexport function isKindDirective(obj: unknown): boolean {\n return directiveSlugOf(obj) !== null;\n}\n\n/**\n * The two-key shell, as it travels on the wire. A TYPE alias, not an interface,\n * so a shell is structurally assignable to `Record<string, unknown>`.\n */\nexport type KindDirectiveShell<Item = Record<string, unknown>> = {\n /** The slug. Serialized FIRST — see the module doc. */\n [KIND_KEY]: string;\n items: Item[];\n};\n\n/**\n * Build the two-key shell with `__kind` FIRST. Never hand-assemble the object\n * literal elsewhere: JS preserves insertion order for string keys, and the\n * first-key rule is what lets the streaming detector type a directive early.\n */\nexport function buildKindDirective<Item>(slug: string, items: Item[]): KindDirectiveShell<Item> {\n return { [KIND_KEY]: slug, items };\n}\n\n/**\n * Mid-stream recognition: the opening of a document whose FIRST key is a\n * reserved directive slug, before the closing brace has arrived. Used by\n * content splitters so a streaming envelope is typed early.\n */\nexport function looksLikeDirectiveHead(content: string): boolean {\n const match = content.trimStart().match(/^\\{\\s*\"__kind\"\\s*:\\s*\"([^\"]*)/);\n return !!match && isReservedDirectiveSlug(match[1]);\n}\n","/**\n * THE ONE LEGACY SURFACE of the Kind Directives protocol — read-only.\n *\n * Stored content written before 2026-08-23 carries the retired 4-key shell\n * (`matrx_version` / `kind` / `type` / `items`). This module translates it into\n * the current two-key shell so `decodeDirective` sees one shape, forever. It\n * never emits, never registers a shape, has no fallback branch, and every use\n * is counted so the containment can be measured. Only `decode.ts` may import\n * it (matrx-frontend's `check-legacy-shim-containment` and aidream's\n * `test_legacy_shim_containment.py` enforce the mirror).\n */\n\nimport { KIND_KEY, buildDirectiveSlug } from \"./grammar\";\n\nconst LEGACY_SENTINEL = \"matrx_version\";\n\nconst CLASS_BY_LEGACY_KIND: Readonly<Record<string, string>> = {\n reference: \"reference\",\n secret: \"secret\",\n validation: \"validation\",\n};\n\nconst LEGACY_SIDE_EFFECT_KINDS: ReadonlySet<string> = new Set([\"output_directive\", \"function\"]);\n\nconst VERB_NOUN_RE = /^(create|update|delete):([a-z][a-z0-9_]*)$/;\n\n// USE COUNTER ON A globalThis SLOT — never a module-level variable. With\n// `splitting: false` dual ESM/CJS output this module is duplicated into the\n// root bundle and the `./directives` bundle; a module local would count per\n// graph and under-report. Never \"clean this up\" into a module local.\nconst USES_SLOT = Symbol.for(\"ai-matrx.content-ir.legacy-shell-uses\");\ntype UsesHolder = typeof globalThis & { [USES_SLOT]?: { count: number } };\nconst uses: { count: number } = ((globalThis as UsesHolder)[USES_SLOT] ??= { count: 0 });\n\nexport function legacyShellUses(): number {\n return uses.count;\n}\n\nexport function resetLegacyShellUses(): void {\n uses.count = 0;\n}\n\n/** True ONLY for a genuine retired-shell directive claim (sentinel + a retired kind token). */\nexport function isLegacyShell(obj: unknown): boolean {\n if (typeof obj !== \"object\" || obj === null || Array.isArray(obj)) return false;\n const record = obj as Record<string, unknown>;\n if (!(LEGACY_SENTINEL in record)) return false;\n const kind = record.kind;\n return (\n typeof kind === \"string\" &&\n (kind in CLASS_BY_LEGACY_KIND || LEGACY_SIDE_EFFECT_KINDS.has(kind))\n );\n}\n\nfunction slugForLegacy(kind: string, type: string): string | null {\n let directiveClass: string;\n let noun: string;\n if (LEGACY_SIDE_EFFECT_KINDS.has(kind)) {\n const match = VERB_NOUN_RE.exec(type);\n if (match) {\n directiveClass = match[1]!;\n noun = match[2]!;\n } else {\n directiveClass = \"action\";\n noun = type;\n }\n } else {\n const mapped = CLASS_BY_LEGACY_KIND[kind];\n if (!mapped) return null;\n directiveClass = mapped;\n noun = type;\n }\n try {\n return buildDirectiveSlug(directiveClass, noun);\n } catch {\n return null;\n }\n}\n\n/** The current two-key shell for a retired one, or null when it cannot be honoured. */\nexport function translateLegacyShell(\n obj: Record<string, unknown>,\n): Record<string, unknown> | null {\n const kind = obj.kind;\n const type = obj.type;\n if (typeof kind !== \"string\" || typeof type !== \"string\") return null;\n const slug = slugForLegacy(kind, type);\n if (slug === null) return null;\n const items = obj.items;\n uses.count += 1;\n return { [KIND_KEY]: slug, items: Array.isArray(items) ? [...items] : [] };\n}\n","/**\n * Decode a Kind Directive — THE one entry point on every client.\n *\n * `decodeDirective()` recognises the shell (current OR, for stored content\n * only, the retired 4-key one), reads the slug, and derives class + noun. A\n * caller only ever sees a parsed {@link DecodedDirective}; nothing downstream\n * inspects a raw shell again.\n *\n * ITEM VALIDATION IS THE SERVER'S. The registered item models live in aidream\n * (`services/content_ir_directives/registry.py`) and validate on apply; a\n * client-side copy of ~120 item models is exactly the drift the merge exists\n * to kill. The client parses identity, routes, and renders. Mirror of aidream\n * `services/content_ir_directives/decode.py`.\n */\n\nimport {\n type DirectiveClass,\n type DirectiveSlug,\n KIND_KEY,\n isReservedDirectiveSlug,\n parseDirectiveSlug,\n} from \"./grammar\";\nimport { isLegacyShell, translateLegacyShell } from \"./legacy-shell\";\n\n/**\n * A well-formed-looking directive that cannot be honoured (a malformed slug, or\n * a retired shell that does not map onto the grammar). Never thrown for \"this\n * isn't a directive\" — that is `null`.\n */\nexport class DirectiveDecodeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DirectiveDecodeError\";\n }\n}\n\nexport interface DecodedDirective {\n /** The parsed slug — class, noun, capability and the position law. */\n readonly parsed: DirectiveSlug;\n readonly slug: string;\n readonly directiveClass: DirectiveClass;\n readonly noun: string;\n readonly items: Record<string, unknown>[];\n /** The two-key shell, normalised — what a confirm POST round-trips. */\n readonly shell: Record<string, unknown>;\n /** True when this arrived in the retired 4-key shell and was translated. */\n readonly legacyShell: boolean;\n}\n\nfunction asObject(value: unknown): Record<string, unknown> | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return null;\n return value as Record<string, unknown>;\n}\n\n/**\n * A typed directive, or `null` when `value` is not a directive at all. Throws\n * {@link DirectiveDecodeError} when it IS one but cannot be honoured.\n */\nexport function decodeDirective(value: unknown): DecodedDirective | null {\n let obj = asObject(value);\n if (obj === null) return null;\n\n let legacy = false;\n if (isLegacyShell(obj)) {\n const translated = translateLegacyShell(obj);\n if (translated === null) {\n throw new DirectiveDecodeError(\n `a retired 4-key shell with kind=${JSON.stringify(obj.kind)} type=${JSON.stringify(obj.type)} does not map onto the Kind Directives grammar. Emit the current shell: {\"${KIND_KEY}\": \"directive_v1_<class>_<noun>\", \"items\": [...]}.`,\n );\n }\n obj = translated;\n legacy = true;\n }\n\n const rawSlug = obj[KIND_KEY];\n if (!isReservedDirectiveSlug(rawSlug)) return null;\n\n const parsed = parseDirectiveSlug(rawSlug);\n if (parsed === null) {\n throw new DirectiveDecodeError(\n `malformed directive slug ${JSON.stringify(rawSlug)} — it claims the reserved \"directive_v\" namespace but does not parse as directive_v<version>_<class>_<noun>.`,\n );\n }\n\n const rawItems = obj.items;\n const items = Array.isArray(rawItems)\n ? rawItems.filter((i): i is Record<string, unknown> => asObject(i) !== null)\n : [];\n\n return {\n parsed,\n slug: parsed.slug,\n directiveClass: parsed.directiveClass,\n noun: parsed.noun,\n items,\n shell: { [KIND_KEY]: parsed.slug, items },\n legacyShell: legacy,\n };\n}\n\n/**\n * The forgiving read used at render seams: `decodeDirective`, but a directive\n * that cannot be honoured comes back as `null` after the reason is handed to\n * `onError`. A render seam must never take a whole message block down over one\n * bad fence — but it must never swallow the reason either.\n */\nexport function tryDecodeDirective(\n value: unknown,\n onError?: (message: string) => void,\n): DecodedDirective | null {\n try {\n return decodeDirective(value);\n } catch (error) {\n onError?.(error instanceof Error ? error.message : \"directive decode failed\");\n return null;\n }\n}\n\n/** `decodeDirective` over a JSON string or an already-parsed value. Non-JSON text is `null`. */\nexport function tryDecodeDirectiveContent(\n content: unknown,\n onError?: (message: string) => void,\n): DecodedDirective | null {\n if (typeof content !== \"string\") return tryDecodeDirective(content, onError);\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch {\n return null;\n }\n return tryDecodeDirective(parsed, onError);\n}\n","/**\n * THE AUTO-VIEW's naming half: every enrolled noun \"instantly has a view\" —\n * the prefix rule gives it a renderer, and this gives it a NAME. A shape the\n * client has never heard of must still read as \"Create Agent · Agents\", never\n * as the raw `agent` token and never as a slug.\n *\n * The catalog (`platform.entity_types` → the server's directive catalog) is the\n * authority for `label` / `family` / `title_column`; a host that mirrors it\n * passes a {@link DirectiveNounCatalog}. Without one — or for a noun the\n * catalog does not carry (a Kind Action like `plan_tree`) — the name degrades\n * to a title-cased token: legible, honestly derived, never blank.\n */\n\nimport type { DirectiveClass } from \"./grammar\";\n\nexport interface DirectiveNounEntry {\n /** The noun's human name — \"Agent\", \"Plan tree\". */\n label?: string | null;\n /** The catalog family (\"Agents\"). */\n family?: string | null;\n /** Which field of a row names it (`name`, `title`, …). */\n titleColumn?: string | null;\n}\n\n/** A host-supplied lookup over the mirrored catalog. `undefined` = not carried. */\nexport type DirectiveNounCatalog = (noun: string) => DirectiveNounEntry | undefined;\n\nexport interface DirectiveDisplay {\n /** The noun's human name — \"Agent\", \"Plan tree\". */\n noun: string;\n /** The catalog family (\"Agents\"), or \"\" when the catalog has none. */\n family: string;\n /** What this directive DOES, in the user's words — \"Create\", \"Reference\". */\n action: string;\n /** One line: \"Create Agent\". */\n title: string;\n}\n\n/** `plan_node_patch` → `Plan node patch`. The honest last resort. */\nexport function titleCaseToken(token: string): string {\n const words = token.replace(/_/g, \" \").trim();\n return words ? words.charAt(0).toUpperCase() + words.slice(1) : token;\n}\n\n/**\n * How a class reads to a human. `action` is deliberately \"Run\": a Kind Action\n * is a named procedure, and \"Action Plan tree\" reads like a noun phrase where a\n * verb belongs. Mirrored by the server's kind-catalog label.\n */\nexport const ACTION_BY_CLASS: Readonly<Record<DirectiveClass, string>> = {\n reference: \"Reference\",\n view: \"View\",\n create: \"Create\",\n update: \"Update\",\n delete: \"Delete\",\n action: \"Run\",\n validation: \"Validate\",\n secret: \"Secret\",\n};\n\nexport function nounLabel(noun: string, catalog?: DirectiveNounCatalog): string {\n const label = catalog?.(noun)?.label;\n return label && label.length > 0 ? label : titleCaseToken(noun);\n}\n\nexport function nounFamily(noun: string, catalog?: DirectiveNounCatalog): string {\n return catalog?.(noun)?.family ?? \"\";\n}\n\nexport function nounTitleColumn(noun: string, catalog?: DirectiveNounCatalog): string | null {\n return catalog?.(noun)?.titleColumn ?? null;\n}\n\n/** Everything a generic card needs to name a directive it cannot render. */\nexport function directiveDisplay(\n directiveClass: DirectiveClass,\n noun: string,\n catalog?: DirectiveNounCatalog,\n): DirectiveDisplay {\n const label = nounLabel(noun, catalog);\n const action = ACTION_BY_CLASS[directiveClass];\n return {\n noun: label,\n family: nounFamily(noun, catalog),\n action,\n title: `${action} ${label}`,\n };\n}\n","/**\n * Naming and summarising ONE item of a directive, for the compact card.\n *\n * THE RULE: a user is never asked to approve a write they cannot identify. The\n * card must say WHAT is about to be created/updated/deleted, derived from\n * authority rather than guesswork, in this order:\n * 1. the noun's catalog `title_column` — the server's own answer to \"what\n * names a row of this table\";\n * 2. the conventional identity fields, in a fixed order;\n * 3. the honest last resort — \"Item 2 of 3\", never a blank chip and never a\n * slug pretending to be a name.\n *\n * Facts are scalars ONLY. Nesting goes to the panel, never into the row.\n */\n\n/** Identity fields, in the order a human would reach for them. */\nconst NAME_KEYS = [\"name\", \"title\", \"label\", \"heading\", \"slug\", \"key\", \"question\", \"summary\"] as const;\n\n/** Never shown as a fact chip — identity, plumbing, or already in the title. */\nconst FACT_EXCLUDE = new Set<string>([\n \"__kind\",\n ...NAME_KEYS,\n \"id\",\n \"description\",\n \"about\",\n \"notes\",\n \"content\",\n \"text\",\n \"body\",\n \"organization_id\",\n \"user_id\",\n \"created_by\",\n \"resource_type\",\n]);\n\nfunction firstString(item: Record<string, unknown>, keys: readonly string[]): string | null {\n for (const key of keys) {\n const value = item[key];\n if (typeof value === \"string\" && value.trim()) return value.trim();\n }\n return null;\n}\n\n/**\n * What to call this item. `titleColumn` is the noun's catalog title column\n * (consulted first); null when the catalog carries none.\n */\nexport function itemTitle(\n item: Record<string, unknown>,\n titleColumn: string | null,\n index: number,\n total: number,\n): string {\n const fromCatalog = titleColumn ? firstString(item, [titleColumn]) : null;\n const name = fromCatalog ?? firstString(item, NAME_KEYS);\n if (name) return name;\n return total > 1 ? `Item ${index + 1} of ${total}` : \"Item\";\n}\n\n/** A one-line subtitle when the item carries prose about itself. */\nexport function itemSubtitle(item: Record<string, unknown>): string | null {\n return firstString(item, [\"description\", \"about\", \"summary\", \"doc\"]);\n}\n\nexport interface ItemFact {\n key: string;\n label: string;\n value: string;\n}\n\n/**\n * A UUID is never a fact. THE UUID RULE: an id is shown as its first segment\n * with a copy control and the full value on hover — which a dense fact chip\n * cannot do. Found in production 2026-09-08: `model_id` rendered as a chip.\n */\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n/** `variable_definitions` → \"variables\". Underscores read as developer output. */\nconst FACT_LABEL_OVERRIDES: Readonly<Record<string, string>> = {\n variable_definitions: \"variables\",\n context_policies: \"context\",\n custom_tools: \"custom tools\",\n};\n\nfunction factLabel(key: string): string {\n return FACT_LABEL_OVERRIDES[key] ?? key.replace(/_/g, \" \");\n}\n\n/**\n * Up to `limit` scalar facts about the item — counts for collections, values\n * for scalars. Nested objects are deliberately absent (they belong in the\n * panel), and so is anything already carried by the title/subtitle.\n */\nexport function itemFacts(item: Record<string, unknown>, limit = 4): ItemFact[] {\n const facts: ItemFact[] = [];\n for (const [key, value] of Object.entries(item)) {\n if (facts.length >= limit) break;\n if (FACT_EXCLUDE.has(key)) continue;\n if (Array.isArray(value)) {\n if (value.length === 0) continue;\n facts.push({ key, label: factLabel(key), value: String(value.length) });\n continue;\n }\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > 40) continue;\n if (UUID_RE.test(trimmed)) continue;\n facts.push({ key, label: factLabel(key), value: trimmed });\n continue;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n facts.push({ key, label: factLabel(key), value: String(value) });\n }\n }\n return facts;\n}\n","/**\n * THE DIRECTIVE⇄KIND SEAM, client side.\n *\n * Arman, 2026-08-26: the envelope / Matrx-Actions system and the Shape (kind)\n * system are ONE system with several methods inside it. They meet at the ITEM.\n * A directive is a CONTAINER; its items are the payload, and when the server's\n * item model is already a `KindModel`, that payload IS a registered kind\n * instance — so the kind system already knows how to validate, render and copy\n * it.\n *\n * The seam is SERVER-DERIVED (`ShapeSpec.item_kind`). Since 2026-09-08 the ONE\n * kind endpoint publishes every directive shape as a KindDescriptor whose\n * `items` EDGE names the item kind, so a client reads it from the same\n * catalog it already holds — {@link directiveItemKindFromEdges}. A host that\n * mirrors the directive catalog manifest instead passes its map as a\n * {@link DirectiveItemKindLookup}. `null` is HONEST, never a gap-filler.\n */\n\nimport { KIND_KEY } from \"./grammar\";\n\n/** A host-supplied lookup: slug → the kind ONE item is, or null. */\nexport type DirectiveItemKindLookup = (slug: string) => string | null;\n\n/** The `items` edge of a directive KindDescriptor, as the kind catalog serves it. */\nexport interface DirectiveItemsEdge {\n field_name?: string;\n fieldPath?: string;\n child_kind?: string;\n childKind?: string;\n}\n\n/** The item kind named by a directive descriptor's `items` edge, or null. */\nexport function directiveItemKindFromEdges(\n edges: readonly DirectiveItemsEdge[] | null | undefined,\n): string | null {\n for (const edge of edges ?? []) {\n const field = edge.field_name ?? edge.fieldPath;\n const child = edge.child_kind ?? edge.childKind;\n if (field === \"items\" && typeof child === \"string\" && child) return child;\n }\n return null;\n}\n\n/**\n * The item, presented the way the kind pipeline expects it: `__kind` FIRST so a\n * consumer types the object from its own first key. `__kind` is ADDED, never\n * overwritten: an item that already carries its marker keeps the value it was\n * emitted with. Null when no kind is known — the caller owns the generic floor.\n */\nexport function asKindInstance(\n item: Record<string, unknown>,\n kind: string | null,\n): Record<string, unknown> | null {\n const existing = item[KIND_KEY];\n const resolved = typeof existing === \"string\" && existing ? existing : kind;\n if (!resolved) return null;\n return { [KIND_KEY]: resolved, ...item };\n}\n"]}