@elevasis/ui 2.32.0 → 2.33.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 (91) hide show
  1. package/dist/app/index.d.ts +3 -0
  2. package/dist/app/index.js +3 -3
  3. package/dist/{chunk-LLRXA7D7.js → chunk-2VYMDNJ3.js} +1 -1
  4. package/dist/{chunk-7KZINJLP.js → chunk-3YZRKADM.js} +4 -4
  5. package/dist/{chunk-MOY4VOHF.js → chunk-4AAZXKLL.js} +1 -1
  6. package/dist/{chunk-RQTWIXJ5.js → chunk-53436UTQ.js} +1 -1
  7. package/dist/{chunk-WQPX44YM.js → chunk-AV2TKVVV.js} +673 -168
  8. package/dist/chunk-CLDCYJQT.js +1 -0
  9. package/dist/chunk-DWXDNT7P.js +145 -0
  10. package/dist/{chunk-T35FWDAB.js → chunk-DYIDXUJS.js} +1089 -158
  11. package/dist/{chunk-IQHU7O5Y.js → chunk-F3MXFE72.js} +1 -1
  12. package/dist/{chunk-5FJJ72HU.js → chunk-FOUYP4JX.js} +1 -1
  13. package/dist/{chunk-QQHOKTJA.js → chunk-H6EFQP2P.js} +39 -2
  14. package/dist/{chunk-5J4PDX26.js → chunk-KW7ZNQD7.js} +16 -2
  15. package/dist/{chunk-ZQOKIGZP.js → chunk-NCEQGEW5.js} +4 -4
  16. package/dist/{chunk-6DWD423K.js → chunk-PIS24NIV.js} +1 -1
  17. package/dist/{chunk-4MFNGNHF.js → chunk-QVTIOT73.js} +2 -2
  18. package/dist/{chunk-GCOQ3TBG.js → chunk-SWMQTF2H.js} +2 -2
  19. package/dist/{chunk-4QK76KIF.js → chunk-UNVRVCXZ.js} +1 -1
  20. package/dist/{chunk-VRNMNB3O.js → chunk-UYRT7SPM.js} +1 -1
  21. package/dist/{chunk-IZWTVFJ2.js → chunk-V6SZ4ECN.js} +6 -3
  22. package/dist/{chunk-YLQEVSOR.js → chunk-WGUEIGPC.js} +202 -54
  23. package/dist/{chunk-QXCDKE2O.js → chunk-WJOE76FI.js} +9 -28
  24. package/dist/{chunk-QTI3KC7D.js → chunk-YENKDBUU.js} +106 -43
  25. package/dist/components/index.d.ts +117 -4
  26. package/dist/components/index.js +24 -23
  27. package/dist/components/navigation/index.js +4 -3
  28. package/dist/execution/index.d.ts +8 -3
  29. package/dist/features/auth/index.d.ts +3 -0
  30. package/dist/features/clients/index.js +8 -7
  31. package/dist/features/crm/index.d.ts +3 -0
  32. package/dist/features/crm/index.js +10 -9
  33. package/dist/features/dashboard/index.d.ts +113 -3
  34. package/dist/features/dashboard/index.js +9 -8
  35. package/dist/features/delivery/index.d.ts +3 -0
  36. package/dist/features/delivery/index.js +9 -8
  37. package/dist/features/knowledge/index.js +8 -18
  38. package/dist/features/lead-gen/index.js +10 -9
  39. package/dist/features/monitoring/index.js +10 -9
  40. package/dist/features/monitoring/requests/index.d.ts +2 -2
  41. package/dist/features/monitoring/requests/index.js +8 -7
  42. package/dist/features/operations/index.d.ts +560 -93
  43. package/dist/features/operations/index.js +13 -12
  44. package/dist/features/settings/index.d.ts +3 -0
  45. package/dist/features/settings/index.js +9 -8
  46. package/dist/hooks/delivery/index.d.ts +3 -0
  47. package/dist/hooks/index.d.ts +210 -6
  48. package/dist/hooks/index.js +8 -7
  49. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +205 -4
  50. package/dist/hooks/published.d.ts +210 -6
  51. package/dist/hooks/published.js +8 -7
  52. package/dist/index.d.ts +565 -95
  53. package/dist/index.js +8 -7
  54. package/dist/initialization/index.d.ts +3 -0
  55. package/dist/knowledge/index.d.ts +577 -215
  56. package/dist/knowledge/index.js +1180 -689
  57. package/dist/knowledge-search-index-P7PR626V.js +1514 -0
  58. package/dist/layout/index.js +1 -1
  59. package/dist/profile/index.d.ts +3 -0
  60. package/dist/provider/index.d.ts +447 -73
  61. package/dist/provider/index.js +7 -6
  62. package/dist/provider/published.d.ts +447 -73
  63. package/dist/provider/published.js +5 -4
  64. package/dist/supabase/index.d.ts +6 -0
  65. package/dist/types/index.d.ts +208 -4
  66. package/dist/utils/index.d.ts +113 -3
  67. package/package.json +39 -39
  68. package/src/README.md +29 -29
  69. package/src/api/README.md +18 -18
  70. package/src/app/README.md +24 -24
  71. package/src/auth/README.md +18 -18
  72. package/src/components/README.md +24 -24
  73. package/src/execution/README.md +16 -16
  74. package/src/features/README.md +28 -28
  75. package/src/graph/README.md +16 -16
  76. package/src/hooks/README.md +23 -23
  77. package/src/initialization/README.md +19 -19
  78. package/src/knowledge/README.md +31 -31
  79. package/src/organization/README.md +18 -18
  80. package/src/profile/README.md +19 -19
  81. package/src/provider/README.md +32 -32
  82. package/src/router/README.md +18 -18
  83. package/src/sse/README.md +13 -13
  84. package/src/test-utils/README.md +7 -7
  85. package/src/theme/README.md +23 -23
  86. package/src/theme/presets/README.md +19 -19
  87. package/src/types/README.md +16 -16
  88. package/src/utils/README.md +18 -18
  89. package/src/zustand/README.md +18 -18
  90. package/dist/chunk-UROTM5OR.js +0 -172
  91. package/dist/knowledge-search-index-5KYPO746.js +0 -1479
@@ -1,74 +1,469 @@
1
1
  import { z } from 'zod';
2
2
 
3
- // ../core/src/organization-model/domains/systems.ts
3
+ // ../core/src/organization-model/ontology.ts
4
+ var OntologyKindSchema = z.enum([
5
+ "object",
6
+ "link",
7
+ "action",
8
+ "catalog",
9
+ "event",
10
+ "interface",
11
+ "value-type",
12
+ "property",
13
+ "group",
14
+ "surface"
15
+ ]);
16
+ var SYSTEM_PATH_PATTERN = "[a-z0-9][a-z0-9-]*(?:\\.[a-z0-9][a-z0-9-]*)*";
17
+ var LOCAL_ID_PATTERN = "[a-z0-9][a-z0-9._-]*";
18
+ var ONTOLOGY_ID_PATTERN = `^(global|${SYSTEM_PATH_PATTERN}):(${OntologyKindSchema.options.join("|")})\\/(${LOCAL_ID_PATTERN})$`;
19
+ var ONTOLOGY_ID_REGEX = new RegExp(ONTOLOGY_ID_PATTERN);
20
+ var OntologyIdSchema = z.string().trim().min(1).max(300).regex(
21
+ ONTOLOGY_ID_REGEX,
22
+ "Ontology IDs must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
23
+ );
24
+ function parseOntologyId(id) {
25
+ const normalized = OntologyIdSchema.parse(id);
26
+ const match = ONTOLOGY_ID_REGEX.exec(normalized);
27
+ if (match === null) {
28
+ throw new Error(`Invalid ontology ID "${id}"`);
29
+ }
30
+ return {
31
+ id: normalized,
32
+ scope: match[1],
33
+ kind: match[2],
34
+ localId: match[3],
35
+ isGlobal: match[1] === "global"
36
+ };
37
+ }
38
+ function formatOntologyId(input) {
39
+ return OntologyIdSchema.parse(`${input.scope}:${input.kind}/${input.localId}`);
40
+ }
41
+ var OntologyReferenceListSchema = z.array(OntologyIdSchema).default([]).optional();
42
+ var OntologyRecordBaseSchema = z.object({
43
+ id: OntologyIdSchema,
44
+ label: z.string().trim().min(1).max(160).optional(),
45
+ description: z.string().trim().min(1).max(2e3).optional(),
46
+ ownerSystemId: z.string().trim().min(1).max(200).optional(),
47
+ aliases: z.array(OntologyIdSchema).optional()
48
+ }).passthrough();
49
+ var OntologyObjectTypeSchema = OntologyRecordBaseSchema.extend({
50
+ properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
51
+ storage: z.record(z.string(), z.unknown()).optional()
52
+ });
53
+ var OntologyLinkTypeSchema = OntologyRecordBaseSchema.extend({
54
+ from: OntologyIdSchema,
55
+ to: OntologyIdSchema,
56
+ cardinality: z.string().trim().min(1).max(80).optional(),
57
+ via: z.string().trim().min(1).max(255).optional()
58
+ });
59
+ var OntologyActionTypeSchema = OntologyRecordBaseSchema.extend({
60
+ actsOn: OntologyReferenceListSchema,
61
+ input: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
62
+ effects: z.array(z.record(z.string(), z.unknown())).optional()
63
+ });
64
+ var OntologyCatalogTypeSchema = OntologyRecordBaseSchema.extend({
65
+ kind: z.string().trim().min(1).max(120).optional(),
66
+ appliesTo: OntologyIdSchema.optional(),
67
+ entries: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
68
+ });
69
+ var OntologyEventTypeSchema = OntologyRecordBaseSchema.extend({
70
+ payload: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
71
+ });
72
+ var OntologyInterfaceTypeSchema = OntologyRecordBaseSchema.extend({
73
+ properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
74
+ });
75
+ var OntologyValueTypeSchema = OntologyRecordBaseSchema.extend({
76
+ primitive: z.string().trim().min(1).max(120).optional()
77
+ });
78
+ var OntologySharedPropertySchema = OntologyRecordBaseSchema.extend({
79
+ valueType: OntologyIdSchema.optional(),
80
+ searchable: z.boolean().optional(),
81
+ pii: z.boolean().optional()
82
+ });
83
+ var OntologyGroupSchema = OntologyRecordBaseSchema.extend({
84
+ members: OntologyReferenceListSchema
85
+ });
86
+ var OntologySurfaceTypeSchema = OntologyRecordBaseSchema.extend({
87
+ route: z.string().trim().min(1).max(500).optional()
88
+ });
89
+ var OntologyScopeSchema = z.object({
90
+ objectTypes: z.record(OntologyIdSchema, OntologyObjectTypeSchema).default({}).optional(),
91
+ linkTypes: z.record(OntologyIdSchema, OntologyLinkTypeSchema).default({}).optional(),
92
+ actionTypes: z.record(OntologyIdSchema, OntologyActionTypeSchema).default({}).optional(),
93
+ catalogTypes: z.record(OntologyIdSchema, OntologyCatalogTypeSchema).default({}).optional(),
94
+ eventTypes: z.record(OntologyIdSchema, OntologyEventTypeSchema).default({}).optional(),
95
+ interfaceTypes: z.record(OntologyIdSchema, OntologyInterfaceTypeSchema).default({}).optional(),
96
+ valueTypes: z.record(OntologyIdSchema, OntologyValueTypeSchema).default({}).optional(),
97
+ sharedProperties: z.record(OntologyIdSchema, OntologySharedPropertySchema).default({}).optional(),
98
+ groups: z.record(OntologyIdSchema, OntologyGroupSchema).default({}).optional(),
99
+ surfaces: z.record(OntologyIdSchema, OntologySurfaceTypeSchema).default({}).optional()
100
+ }).default({});
101
+ var DEFAULT_ONTOLOGY_SCOPE = {
102
+ valueTypes: {
103
+ "global:value-type/uuid": {
104
+ id: "global:value-type/uuid",
105
+ label: "UUID",
106
+ primitive: "string"
107
+ },
108
+ "global:value-type/text": {
109
+ id: "global:value-type/text",
110
+ label: "Text",
111
+ primitive: "string"
112
+ },
113
+ "global:value-type/url": {
114
+ id: "global:value-type/url",
115
+ label: "URL",
116
+ primitive: "string"
117
+ },
118
+ "global:value-type/email": {
119
+ id: "global:value-type/email",
120
+ label: "Email",
121
+ primitive: "string"
122
+ }
123
+ }
124
+ };
125
+ var SCOPE_KIND = {
126
+ objectTypes: "object",
127
+ linkTypes: "link",
128
+ actionTypes: "action",
129
+ catalogTypes: "catalog",
130
+ eventTypes: "event",
131
+ interfaceTypes: "interface",
132
+ valueTypes: "value-type",
133
+ sharedProperties: "property",
134
+ groups: "group",
135
+ surfaces: "surface"
136
+ };
137
+ var SCOPE_KEYS = Object.keys(SCOPE_KIND);
138
+ function ontologyGraphNodeId(id) {
139
+ return `ontology:${OntologyIdSchema.parse(id)}`;
140
+ }
141
+ function listResolvedOntologyRecords(index) {
142
+ return SCOPE_KEYS.flatMap((scopeKey) => {
143
+ const kind = SCOPE_KIND[scopeKey];
144
+ return Object.entries(index[scopeKey]).sort(([leftId], [rightId]) => leftId.localeCompare(rightId)).map(([id, record]) => ({
145
+ id,
146
+ kind,
147
+ record
148
+ }));
149
+ });
150
+ }
151
+ function originFromContext(context) {
152
+ return {
153
+ kind: context.kind,
154
+ source: context.source,
155
+ path: context.path,
156
+ ...context.systemPath !== void 0 ? { systemPath: context.systemPath } : {},
157
+ ...context.legacyId !== void 0 ? { legacyId: context.legacyId } : {}
158
+ };
159
+ }
160
+ function createEmptyIndex() {
161
+ return {
162
+ objectTypes: {},
163
+ linkTypes: {},
164
+ actionTypes: {},
165
+ catalogTypes: {},
166
+ eventTypes: {},
167
+ interfaceTypes: {},
168
+ valueTypes: {},
169
+ sharedProperties: {},
170
+ groups: {},
171
+ surfaces: {}
172
+ };
173
+ }
174
+ function sortResolvedOntologyIndex(index) {
175
+ const sorted = createEmptyIndex();
176
+ for (const scopeKey of SCOPE_KEYS) {
177
+ const target = sorted[scopeKey];
178
+ for (const [id, record] of Object.entries(index[scopeKey]).sort(
179
+ ([leftId], [rightId]) => leftId.localeCompare(rightId)
180
+ )) {
181
+ target[id] = record;
182
+ }
183
+ }
184
+ return sorted;
185
+ }
186
+ function childSystemsOf(system) {
187
+ return system.systems ?? system.subsystems ?? {};
188
+ }
189
+ function addRecord(index, diagnostics, sourcesById, scopeKey, record, context) {
190
+ let parsed;
191
+ try {
192
+ parsed = parseOntologyId(record.id);
193
+ } catch {
194
+ diagnostics.push({
195
+ code: "invalid_ontology_id",
196
+ message: `Invalid ontology ID "${record.id}" from ${context.source} at ${context.path.join(".")}`,
197
+ id: record.id,
198
+ path: context.path,
199
+ source: context.source,
200
+ origin: originFromContext(context)
201
+ });
202
+ return;
203
+ }
204
+ const expectedKind = SCOPE_KIND[scopeKey];
205
+ if (parsed.kind !== expectedKind) {
206
+ diagnostics.push({
207
+ code: "ontology_kind_mismatch",
208
+ message: `Ontology ID "${record.id}" has kind "${parsed.kind}" but was authored in ${scopeKey} (${expectedKind}) at ${context.path.join(".")}`,
209
+ id: record.id,
210
+ path: context.path,
211
+ source: context.source,
212
+ origin: originFromContext(context)
213
+ });
214
+ return;
215
+ }
216
+ const existing = sourcesById.get(parsed.id);
217
+ if (existing !== void 0) {
218
+ diagnostics.push({
219
+ code: "duplicate_ontology_id",
220
+ message: `Duplicate ontology ID "${parsed.id}" from ${context.source} at ${context.path.join(".")} conflicts with ${existing.source} at ${existing.path.join(".")}`,
221
+ id: parsed.id,
222
+ path: context.path,
223
+ source: context.source,
224
+ origin: originFromContext(context),
225
+ existingSource: existing.source,
226
+ existingOrigin: originFromContext(existing)
227
+ });
228
+ return;
229
+ }
230
+ sourcesById.set(parsed.id, context);
231
+ index[scopeKey][parsed.id] = {
232
+ ...record,
233
+ origin: originFromContext(context)
234
+ };
235
+ }
236
+ function addScope(index, diagnostics, sourcesById, scope, source, path) {
237
+ if (scope === void 0) return;
238
+ for (const scopeKey of SCOPE_KEYS) {
239
+ const records = scope[scopeKey] ?? {};
240
+ for (const [key, record] of Object.entries(records)) {
241
+ addRecord(index, diagnostics, sourcesById, scopeKey, record, {
242
+ source,
243
+ path: [...path, scopeKey, key],
244
+ kind: "authored",
245
+ systemPath: source.startsWith("system:") ? source.slice("system:".length, -".ontology".length) : void 0
246
+ });
247
+ }
248
+ }
249
+ }
250
+ function legacyObjectId(entity) {
251
+ return formatOntologyId({ scope: entity.ownedBySystemId, kind: "object", localId: entity.id });
252
+ }
253
+ function legacyActionOwner(action, entities) {
254
+ const firstAffectedEntityId = action.affects?.find((entityId) => entities[entityId] !== void 0);
255
+ if (firstAffectedEntityId !== void 0) {
256
+ return entities[firstAffectedEntityId].ownedBySystemId;
257
+ }
258
+ if (typeof action.scope === "object") {
259
+ return action.scope.domain;
260
+ }
261
+ return "global";
262
+ }
263
+ function addLegacyEntityProjections(index, diagnostics, sourcesById, entities) {
264
+ for (const entity of Object.values(entities)) {
265
+ const objectType = {
266
+ id: legacyObjectId(entity),
267
+ label: entity.label,
268
+ description: entity.description,
269
+ ownerSystemId: entity.ownedBySystemId,
270
+ ...entity.table !== void 0 ? {
271
+ storage: {
272
+ kind: "table",
273
+ table: entity.table
274
+ }
275
+ } : {},
276
+ ...entity.rowSchema !== void 0 ? { rowSchema: entity.rowSchema } : {},
277
+ ...entity.stateCatalogId !== void 0 ? { stateCatalogId: entity.stateCatalogId } : {}
278
+ };
279
+ addRecord(index, diagnostics, sourcesById, "objectTypes", objectType, {
280
+ source: "legacy.entities",
281
+ path: ["entities", entity.id],
282
+ kind: "projected",
283
+ systemPath: entity.ownedBySystemId,
284
+ legacyId: entity.id
285
+ });
286
+ entity.links?.forEach((link, linkIndex) => {
287
+ const targetEntity = entities[link.toEntity];
288
+ if (targetEntity === void 0) return;
289
+ const linkType = {
290
+ id: formatOntologyId({
291
+ scope: entity.ownedBySystemId,
292
+ kind: "link",
293
+ localId: `${entity.id}-${link.toEntity}-${linkIndex}`
294
+ }),
295
+ label: link.label ?? link.kind,
296
+ ownerSystemId: entity.ownedBySystemId,
297
+ from: legacyObjectId(entity),
298
+ to: legacyObjectId(targetEntity),
299
+ cardinality: link.kind,
300
+ ...link.via !== void 0 ? { via: link.via } : {}
301
+ };
302
+ addRecord(index, diagnostics, sourcesById, "linkTypes", linkType, {
303
+ source: "legacy.entities.links",
304
+ path: ["entities", entity.id, "links", linkIndex],
305
+ kind: "projected",
306
+ systemPath: entity.ownedBySystemId,
307
+ legacyId: `${entity.id}.links.${linkIndex}`
308
+ });
309
+ });
310
+ }
311
+ }
312
+ function addLegacyActionProjections(index, diagnostics, sourcesById, actions, entities) {
313
+ for (const action of Object.values(actions)) {
314
+ const ownerSystemId = legacyActionOwner(action, entities);
315
+ const actionType = {
316
+ id: formatOntologyId({ scope: ownerSystemId, kind: "action", localId: action.id }),
317
+ label: action.label,
318
+ description: action.description,
319
+ ownerSystemId,
320
+ actsOn: action.affects?.map((entityId) => entities[entityId] ? legacyObjectId(entities[entityId]) : void 0).filter((id) => id !== void 0),
321
+ ...action.resourceId !== void 0 ? { resourceId: action.resourceId } : {},
322
+ ...action.invocations !== void 0 ? { invocations: action.invocations } : {},
323
+ ...action.lifecycle !== void 0 ? { lifecycle: action.lifecycle } : {},
324
+ legacyActionId: action.id
325
+ };
326
+ addRecord(index, diagnostics, sourcesById, "actionTypes", actionType, {
327
+ source: "legacy.actions",
328
+ path: ["actions", action.id],
329
+ kind: "projected",
330
+ systemPath: ownerSystemId,
331
+ legacyId: action.id
332
+ });
333
+ }
334
+ }
335
+ function addSystemContentProjections(index, diagnostics, sourcesById, systemPath, system, schemaPath) {
336
+ const content = system.content ?? {};
337
+ for (const [localId, node] of Object.entries(content)) {
338
+ if (node.kind !== "schema") continue;
339
+ const entries = Object.fromEntries(
340
+ Object.entries(content).filter(([, candidate]) => candidate.parentContentId === localId).map(([entryId, candidate]) => [
341
+ entryId,
342
+ {
343
+ label: candidate.label ?? entryId,
344
+ type: candidate.type,
345
+ ...candidate.description !== void 0 ? { description: candidate.description } : {},
346
+ ...candidate.data !== void 0 ? candidate.data : {}
347
+ }
348
+ ])
349
+ );
350
+ const catalogType = {
351
+ id: formatOntologyId({ scope: systemPath, kind: "catalog", localId }),
352
+ label: node.label ?? localId,
353
+ description: node.description,
354
+ ownerSystemId: systemPath,
355
+ kind: node.type,
356
+ ...typeof node.data?.["entityId"] === "string" ? { appliesTo: formatOntologyId({ scope: systemPath, kind: "object", localId: node.data["entityId"] }) } : {},
357
+ ...Object.keys(entries).length > 0 ? { entries } : {},
358
+ ...node.data !== void 0 ? { data: node.data } : {}
359
+ };
360
+ addRecord(index, diagnostics, sourcesById, "catalogTypes", catalogType, {
361
+ source: "legacy.system.content",
362
+ path: [...schemaPath, "content", localId],
363
+ kind: "projected",
364
+ systemPath,
365
+ legacyId: `${systemPath}:${localId}`
366
+ });
367
+ }
368
+ }
369
+ function addSystemScopes(index, diagnostics, sourcesById, systems, prefix, schemaPath) {
370
+ for (const [key, system] of Object.entries(systems)) {
371
+ const systemPath = prefix ? `${prefix}.${key}` : key;
372
+ const currentPath = [...schemaPath, key];
373
+ addScope(index, diagnostics, sourcesById, system.ontology, `system:${systemPath}.ontology`, [
374
+ ...currentPath,
375
+ "ontology"
376
+ ]);
377
+ addSystemContentProjections(index, diagnostics, sourcesById, systemPath, system, currentPath);
378
+ addSystemScopes(index, diagnostics, sourcesById, childSystemsOf(system), systemPath, [
379
+ ...currentPath,
380
+ system.systems !== void 0 ? "systems" : "subsystems"
381
+ ]);
382
+ }
383
+ }
384
+ function compileOrganizationOntology(model) {
385
+ const ontology = createEmptyIndex();
386
+ const diagnostics = [];
387
+ const sourcesById = /* @__PURE__ */ new Map();
388
+ addScope(ontology, diagnostics, sourcesById, model.ontology, "organization.ontology", ["ontology"]);
389
+ addSystemScopes(ontology, diagnostics, sourcesById, model.systems ?? {}, "", ["systems"]);
390
+ addLegacyEntityProjections(ontology, diagnostics, sourcesById, model.entities ?? {});
391
+ addLegacyActionProjections(ontology, diagnostics, sourcesById, model.actions ?? {}, model.entities ?? {});
392
+ return { ontology: sortResolvedOntologyIndex(ontology), diagnostics };
393
+ }
4
394
  var ORGANIZATION_MODEL_ICON_TOKENS = [
5
- "nav.dashboard",
6
- "nav.calendar",
7
- "nav.sales",
8
- "nav.crm",
9
- "nav.lead-gen",
10
- "nav.projects",
11
- "nav.operations",
12
- "nav.monitoring",
13
- "nav.knowledge",
14
- "nav.settings",
15
- "nav.admin",
16
- "nav.archive",
17
- "knowledge.playbook",
18
- "knowledge.strategy",
19
- "knowledge.reference",
20
- "feature.dashboard",
21
- "feature.calendar",
22
- "feature.business",
23
- "feature.sales",
24
- "feature.crm",
25
- "feature.finance",
26
- "feature.lead-gen",
27
- "feature.platform",
28
- "feature.projects",
29
- "feature.operations",
30
- "feature.knowledge",
31
- "feature.monitoring",
32
- "feature.settings",
33
- "feature.admin",
34
- "feature.archive",
35
- "feature.seo",
36
- "resource.agent",
37
- "resource.workflow",
38
- "resource.integration",
39
- "resource.database",
40
- "resource.user",
41
- "resource.team",
42
- "integration.gmail",
43
- "integration.google-sheets",
44
- "integration.attio",
45
- "surface.dashboard",
46
- "surface.calendar",
47
- "surface.overview",
48
- "surface.command-view",
49
- "surface.command-queue",
50
- "surface.pipeline",
51
- "surface.lists",
52
- "surface.resources",
53
- "surface.settings",
54
- "status.success",
55
- "status.error",
56
- "status.warning",
57
- "status.info",
58
- "status.pending",
59
- "action.approve",
60
- "action.reject",
61
- "action.retry",
62
- "action.edit",
63
- "action.view",
64
- "action.launch",
65
- "action.message",
66
- "action.escalate",
67
- "action.promote",
68
- "action.submit",
69
- "action.email"
395
+ // Navigation / app areas
396
+ "dashboard",
397
+ "calendar",
398
+ "sales",
399
+ "crm",
400
+ "lead-gen",
401
+ "projects",
402
+ "operations",
403
+ "monitoring",
404
+ "knowledge",
405
+ "settings",
406
+ "admin",
407
+ "archive",
408
+ "business",
409
+ "finance",
410
+ "platform",
411
+ "seo",
412
+ // Knowledge kinds
413
+ "playbook",
414
+ "strategy",
415
+ "reference",
416
+ // Resource kinds
417
+ "agent",
418
+ "workflow",
419
+ "integration",
420
+ "database",
421
+ "user",
422
+ "team",
423
+ // Integration specifics
424
+ "gmail",
425
+ "google-sheets",
426
+ "attio",
427
+ // Surface / UI views
428
+ "overview",
429
+ "command-view",
430
+ "command-queue",
431
+ "pipeline",
432
+ "lists",
433
+ "resources",
434
+ // Actions
435
+ "approve",
436
+ "reject",
437
+ "retry",
438
+ "edit",
439
+ "view",
440
+ "launch",
441
+ "message",
442
+ "escalate",
443
+ "promote",
444
+ "submit",
445
+ "email",
446
+ // Status
447
+ "success",
448
+ "error",
449
+ "warning",
450
+ "info",
451
+ "pending",
452
+ // OM / UI group icons
453
+ "bolt",
454
+ "building",
455
+ "briefcase",
456
+ "apps",
457
+ "graph",
458
+ "shield",
459
+ "users",
460
+ "chart-bar",
461
+ "search"
70
462
  ];
71
- var CustomIconTokenSchema = z.string().trim().max(80).regex(/^custom\.[a-z0-9]+(?:[-._][a-z0-9]+)*$/, "Custom icon tokens must start with custom.");
463
+ var CustomIconTokenSchema = z.string().trim().max(80).regex(
464
+ /^custom\.[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
465
+ 'Custom icon tokens must start with "custom." followed by lowercase alphanumeric segments'
466
+ );
72
467
  var OrganizationModelBuiltinIconTokenSchema = z.enum(ORGANIZATION_MODEL_ICON_TOKENS);
73
468
  var OrganizationModelIconTokenSchema = z.union([
74
469
  OrganizationModelBuiltinIconTokenSchema,
@@ -430,7 +825,99 @@ var LEAD_GEN_ACTION_ENTRIES = Object.fromEntries(
430
825
  return [parsed.id, parsed];
431
826
  })
432
827
  );
433
- var DEFAULT_ORGANIZATION_MODEL_ACTIONS = LEAD_GEN_ACTION_ENTRIES;
828
+ var CRM_ACTION_ENTRY_INPUTS = [
829
+ {
830
+ id: "send_reply",
831
+ order: 210,
832
+ label: "Send Reply",
833
+ description: "Send a contextual reply for an active CRM deal.",
834
+ scope: { domain: "sales" },
835
+ resourceId: "crm-send-reply-workflow",
836
+ affects: ["crm.deal"]
837
+ },
838
+ {
839
+ id: "send_link",
840
+ order: 220,
841
+ label: "Send Booking Link",
842
+ description: "Send a booking link to move a deal toward a scheduled call.",
843
+ scope: { domain: "sales" },
844
+ resourceId: "crm-send-booking-link-workflow",
845
+ affects: ["crm.deal"]
846
+ },
847
+ {
848
+ id: "send_nudge",
849
+ order: 230,
850
+ label: "Send Nudge",
851
+ description: "Send a follow-up nudge for a stalled CRM deal.",
852
+ scope: { domain: "sales" },
853
+ resourceId: "crm-send-nudge-workflow",
854
+ affects: ["crm.deal"]
855
+ },
856
+ {
857
+ id: "rebook",
858
+ order: 240,
859
+ label: "Rebook",
860
+ description: "Rebook a missed or rescheduled CRM appointment.",
861
+ scope: { domain: "sales" },
862
+ resourceId: "crm-rebook-workflow",
863
+ affects: ["crm.deal"]
864
+ },
865
+ {
866
+ id: "move_to_proposal",
867
+ order: 250,
868
+ label: "Move to Proposal",
869
+ description: "Advance a qualified CRM deal into the proposal stage.",
870
+ scope: { domain: "sales" },
871
+ resourceId: "move_to_proposal-workflow",
872
+ affects: ["crm.deal"]
873
+ },
874
+ {
875
+ id: "move_to_closing",
876
+ order: 260,
877
+ label: "Move to Closing",
878
+ description: "Advance a proposal-stage CRM deal into closing.",
879
+ scope: { domain: "sales" },
880
+ resourceId: "move_to_closing-workflow",
881
+ affects: ["crm.deal"]
882
+ },
883
+ {
884
+ id: "move_to_closed_won",
885
+ order: 270,
886
+ label: "Close Won",
887
+ description: "Mark a CRM deal as closed won.",
888
+ scope: { domain: "sales" },
889
+ resourceId: "move_to_closed_won-workflow",
890
+ affects: ["crm.deal"]
891
+ },
892
+ {
893
+ id: "move_to_closed_lost",
894
+ order: 280,
895
+ label: "Close Lost",
896
+ description: "Mark a CRM deal as closed lost.",
897
+ scope: { domain: "sales" },
898
+ resourceId: "move_to_closed_lost-workflow",
899
+ affects: ["crm.deal"]
900
+ },
901
+ {
902
+ id: "move_to_nurturing",
903
+ order: 290,
904
+ label: "Move to Nurturing",
905
+ description: "Move a CRM deal into nurturing for future follow-up.",
906
+ scope: { domain: "sales" },
907
+ resourceId: "move_to_nurturing-workflow",
908
+ affects: ["crm.deal"]
909
+ }
910
+ ];
911
+ var CRM_ACTION_ENTRIES = Object.fromEntries(
912
+ CRM_ACTION_ENTRY_INPUTS.map((action) => {
913
+ const parsed = ActionSchema.parse(action);
914
+ return [parsed.id, parsed];
915
+ })
916
+ );
917
+ var DEFAULT_ORGANIZATION_MODEL_ACTIONS = {
918
+ ...LEAD_GEN_ACTION_ENTRIES,
919
+ ...CRM_ACTION_ENTRIES
920
+ };
434
921
  var ContentNodeBaseSchema = z.object({
435
922
  /** Human-readable label for the content node. */
436
923
  label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
@@ -491,6 +978,17 @@ var SystemUiSchema = z.object({
491
978
  icon: IconNameSchema.optional(),
492
979
  order: z.number().int().optional()
493
980
  });
981
+ var JsonValueSchema = z.lazy(
982
+ () => z.union([
983
+ z.string(),
984
+ z.number(),
985
+ z.boolean(),
986
+ z.null(),
987
+ z.array(JsonValueSchema),
988
+ z.record(z.string(), JsonValueSchema)
989
+ ])
990
+ );
991
+ var SystemConfigSchema = z.record(z.string().trim().min(1).max(200), JsonValueSchema).default({}).optional();
494
992
  var SystemEntrySchema = z.object({
495
993
  /** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
496
994
  id: SystemIdSchema,
@@ -536,11 +1034,21 @@ var SystemEntrySchema = z.object({
536
1034
  /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
537
1035
  order: z.number(),
538
1036
  /**
539
- * System-scoped operational data, co-located with the owning system.
540
- * Per L1, L3, L13: keyed by local NodeId (the key is the local id; qualified
541
- * id is `<system-path>:<local-id>`, computed by graph projection).
542
- * Per L14: every ContentNode carries both `kind` and `type`.
543
- * Per D2: unregistered (kind, type) pairs parse successfully.
1037
+ * System-local JSON settings and defaults. Strongly typed OM fields,
1038
+ * secrets, credentials, and runtime state stay outside this bucket.
1039
+ */
1040
+ config: SystemConfigSchema,
1041
+ /**
1042
+ * System-owned ontology declarations. `systems` is now the canonical child
1043
+ * key; this scope holds the object, action, catalog, link, event, and
1044
+ * shared contract records owned by this system.
1045
+ */
1046
+ ontology: OntologyScopeSchema.optional(),
1047
+ /**
1048
+ * @deprecated Compatibility-only bridge for old tenant content nodes and
1049
+ * migration readers. New schema/catalog authoring belongs in ontology;
1050
+ * new system-local settings belong in config. Bridge nodes are keyed by
1051
+ * local NodeId and may still project to content-node:* graph IDs.
544
1052
  */
545
1053
  content: z.record(z.string().trim().min(1).max(200), ContentNodeSchema).optional(),
546
1054
  /**
@@ -550,14 +1058,17 @@ var SystemEntrySchema = z.object({
550
1058
  * Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
551
1059
  * position-derived paths. Both still exist on this schema for backward compat.
552
1060
  */
1061
+ systems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional(),
1062
+ /** @deprecated Use systems. Accepted as a compatibility alias during the ontology bridge. */
553
1063
  subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
554
1064
  }).refine((system) => system.label !== void 0 || system.title !== void 0, {
555
1065
  path: ["label"],
556
1066
  message: "System must provide label or title"
557
1067
  }).transform((system) => {
558
- if (system.status === void 0) return system;
1068
+ const normalizedSystem = system.systems !== void 0 && system.subsystems === void 0 ? { ...system, subsystems: system.systems } : system;
1069
+ if (normalizedSystem.status === void 0) return normalizedSystem;
559
1070
  console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
560
- return system.lifecycle === void 0 ? { ...system, lifecycle: system.status } : system;
1071
+ return normalizedSystem.lifecycle === void 0 ? { ...normalizedSystem, lifecycle: normalizedSystem.status } : normalizedSystem;
561
1072
  });
562
1073
  var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
563
1074
  message: "Each system entry id must match its map key"
@@ -633,6 +1144,7 @@ z.enum(["workflow", "agent", "integration", "script"]).meta({ label: "Resource k
633
1144
  var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Governance status", color: "teal" });
634
1145
  var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "platform"]).meta({ label: "Agent kind", color: "violet" });
635
1146
  var ScriptResourceLanguageSchema = z.enum(["shell", "sql", "typescript", "python"]).meta({ label: "Language" });
1147
+ var CodeReferenceRoleSchema = z.enum(["entrypoint", "handler", "schema", "test", "docs", "config"]).meta({ label: "Code reference role", color: "blue" });
636
1148
  var ResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
637
1149
  var EventIdSchema = z.string().trim().min(1).max(300).regex(
638
1150
  /^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*:[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
@@ -650,6 +1162,28 @@ EventEmissionDescriptorSchema.extend({
650
1162
  ownerId: z.union([ResourceIdSchema, ModelIdSchema]),
651
1163
  ownerKind: z.enum(["resource", "entity"]).meta({ label: "Owner kind" })
652
1164
  });
1165
+ var ResourceOntologyBindingSchema = z.object({
1166
+ actions: z.array(OntologyIdSchema).optional(),
1167
+ primaryAction: OntologyIdSchema.optional(),
1168
+ reads: z.array(OntologyIdSchema).optional(),
1169
+ writes: z.array(OntologyIdSchema).optional(),
1170
+ usesCatalogs: z.array(OntologyIdSchema).optional(),
1171
+ emits: z.array(OntologyIdSchema).optional()
1172
+ }).superRefine((binding, ctx) => {
1173
+ if (binding.primaryAction === void 0) return;
1174
+ if (binding.actions?.includes(binding.primaryAction)) return;
1175
+ ctx.addIssue({
1176
+ code: z.ZodIssueCode.custom,
1177
+ path: ["primaryAction"],
1178
+ message: "Resource ontology primaryAction must be included in actions"
1179
+ });
1180
+ });
1181
+ var CodeReferenceSchema = z.object({
1182
+ path: z.string().trim().min(1).max(500).regex(/^[A-Za-z0-9_./$@()[\] -]+$/, "Code reference paths must be repo-relative paths"),
1183
+ role: CodeReferenceRoleSchema,
1184
+ symbol: z.string().trim().min(1).max(200).optional(),
1185
+ description: z.string().trim().min(1).max(300).optional()
1186
+ });
653
1187
  var ResourceEntryBaseSchema = z.object({
654
1188
  /** Canonical resource id; runtime resourceId derives from this value. */
655
1189
  id: ResourceIdSchema,
@@ -657,14 +1191,24 @@ var ResourceEntryBaseSchema = z.object({
657
1191
  order: z.number().default(0),
658
1192
  /** Required single System membership — value is a dot-separated system path (e.g. "sales.lead-gen"). */
659
1193
  systemPath: SystemPathSchema.meta({ ref: "system" }),
1194
+ /** Executable display title owned by the OM Resource descriptor. */
1195
+ title: LabelSchema.optional(),
1196
+ /** Executable display description owned by the OM Resource descriptor. */
1197
+ description: DescriptionSchema.optional(),
660
1198
  /** Optional role responsible for maintaining this resource. */
661
1199
  ownerRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
662
- status: ResourceGovernanceStatusSchema
1200
+ status: ResourceGovernanceStatusSchema,
1201
+ /**
1202
+ * Ontology contract bindings for the semantic work this resource performs.
1203
+ * `emits` stays nested here so top-level resource emits descriptors remain
1204
+ * compatible with graph event projection during the bridge.
1205
+ */
1206
+ ontology: ResourceOntologyBindingSchema.optional(),
1207
+ /** Repo-relative implementation breadcrumbs for agents and operators. */
1208
+ codeRefs: z.array(CodeReferenceSchema).default([])
663
1209
  });
664
1210
  var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
665
1211
  kind: z.literal("workflow"),
666
- /** Mirrors WorkflowConfig.actionKey when the runtime workflow has one. */
667
- actionKey: z.string().trim().min(1).max(255).optional(),
668
1212
  emits: z.array(EventEmissionDescriptorSchema).optional()
669
1213
  });
670
1214
  var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
@@ -706,6 +1250,9 @@ var ResourcesDomainSchema = z.record(z.string(), ResourceEntrySchema).refine((re
706
1250
  var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {};
707
1251
 
708
1252
  // ../core/src/organization-model/helpers.ts
1253
+ function childSystemsOf2(system) {
1254
+ return system.systems ?? system.subsystems ?? {};
1255
+ }
709
1256
  function defaultPathFor(id) {
710
1257
  return `/${id.replaceAll(".", "/")}`;
711
1258
  }
@@ -753,7 +1300,7 @@ function getSystem(model, path) {
753
1300
  for (const seg of segments) {
754
1301
  node = current[seg];
755
1302
  if (node === void 0) return void 0;
756
- current = node.subsystems ?? {};
1303
+ current = childSystemsOf2(node);
757
1304
  }
758
1305
  return node;
759
1306
  }
@@ -765,7 +1312,7 @@ function getSystemAncestors(model, path) {
765
1312
  const node = current[seg];
766
1313
  if (node === void 0) return [];
767
1314
  result.push(node);
768
- current = node.subsystems ?? {};
1315
+ current = childSystemsOf2(node);
769
1316
  }
770
1317
  return result;
771
1318
  }
@@ -775,8 +1322,9 @@ function listAllSystems(model) {
775
1322
  for (const [localId, system] of Object.entries(map)) {
776
1323
  const fullPath = prefix ? `${prefix}.${localId}` : localId;
777
1324
  results.push({ path: fullPath, system });
778
- if (system.subsystems) {
779
- walk(system.subsystems, fullPath);
1325
+ const childSystems = childSystemsOf2(system);
1326
+ if (Object.keys(childSystems).length > 0) {
1327
+ walk(childSystems, fullPath);
780
1328
  }
781
1329
  }
782
1330
  }
@@ -792,6 +1340,30 @@ function getContent(model, qualifiedId) {
792
1340
  const system = getSystem(model, systemPath);
793
1341
  return system?.content?.[localId];
794
1342
  }
1343
+ function isPlainJsonObject(value) {
1344
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1345
+ }
1346
+ function mergeJsonConfig(base, override) {
1347
+ const result = { ...base };
1348
+ for (const [key, value] of Object.entries(override)) {
1349
+ const existing = result[key];
1350
+ result[key] = isPlainJsonObject(existing) && isPlainJsonObject(value) ? mergeJsonConfig(existing, value) : value;
1351
+ }
1352
+ return result;
1353
+ }
1354
+ function resolveSystemConfig(model, path) {
1355
+ const system = getSystem(model, path);
1356
+ if (system === void 0) return {};
1357
+ let resolved = {};
1358
+ for (const node of Object.values(system.content ?? {})) {
1359
+ if (node.kind !== "config" || node.type !== "kv") continue;
1360
+ const entries = node.data?.entries;
1361
+ if (isPlainJsonObject(entries)) {
1362
+ resolved = mergeJsonConfig(resolved, entries);
1363
+ }
1364
+ }
1365
+ return mergeJsonConfig(resolved, system.config ?? {});
1366
+ }
795
1367
  function getResourcesForSystem(model, systemPath, options = {}) {
796
1368
  const { includeDescendants = false } = options;
797
1369
  const prefix = systemPath + ".";
@@ -1843,19 +2415,29 @@ var KnowledgeTargetKindSchema = z.enum([
1843
2415
  "goal",
1844
2416
  "customer-segment",
1845
2417
  "offering",
2418
+ "ontology",
1846
2419
  // D4: content nodes are a valid knowledge target after compound-domain data moved into system.content
1847
2420
  "content-node"
1848
2421
  ]).meta({ label: "Target kind" });
1849
2422
  var KnowledgeTargetRefSchema = z.object({
1850
2423
  kind: KnowledgeTargetKindSchema,
1851
- // D4: content-node targets use a qualified id format '<system-path>:<local-content-id>'
1852
- // which contains a colon separator and cannot satisfy ModelIdSchema. Use a permissive
1853
- // string schema here; business-logic validation of target existence is done in
1854
- // OrganizationModelSchema.superRefine (knowledgeTargetExists).
2424
+ // D4: content-node targets use a qualified id format '<system-path>:<local-content-id>'.
2425
+ // Ontology targets use the canonical '<scope>:<kind>/<local-id>' ontology id format.
2426
+ // Business-logic validation of target existence is done in OrganizationModelSchema.superRefine.
1855
2427
  id: z.string().trim().min(1).max(300)
2428
+ }).superRefine((target, ctx) => {
2429
+ if (target.kind !== "ontology") return;
2430
+ const result = OntologyIdSchema.safeParse(target.id);
2431
+ if (!result.success) {
2432
+ ctx.addIssue({
2433
+ code: z.ZodIssueCode.custom,
2434
+ path: ["id"],
2435
+ message: "Ontology knowledge targets must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
2436
+ });
2437
+ }
1856
2438
  });
1857
2439
  var LegacyKnowledgeLinkSchema = z.object({
1858
- nodeId: NodeIdStringSchema
2440
+ nodeId: z.union([NodeIdStringSchema, z.templateLiteral(["ontology:", OntologyIdSchema])])
1859
2441
  });
1860
2442
  var CanonicalKnowledgeLinkSchema = z.object({
1861
2443
  target: KnowledgeTargetRefSchema
@@ -1886,6 +2468,8 @@ var OrgKnowledgeNodeSchema = z.object({
1886
2468
  icon: IconNameSchema.optional(),
1887
2469
  /** Canonical documentation URL when body content is a local summary. */
1888
2470
  externalUrl: z.string().trim().url().max(500).optional(),
2471
+ /** Optional generated source file path for local MDX-backed knowledge nodes. */
2472
+ sourceFilePath: z.string().trim().min(1).max(500).optional(),
1889
2473
  /** Raw MDX string. Phase 2 will introduce a structured block format. */
1890
2474
  body: z.string().trim().min(1),
1891
2475
  /**
@@ -1899,6 +2483,73 @@ var OrgKnowledgeNodeSchema = z.object({
1899
2483
  updatedAt: z.string().trim().min(1).max(50)
1900
2484
  });
1901
2485
  var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
2486
+ var SecretLikeMetadataKeySchema = /(?:secret|password|passwd|token|api[-_]?key|credential|private[-_]?key)/i;
2487
+ var SecretLikeMetadataValueSchema = /(?:sk-[A-Za-z0-9_-]{12,}|pk_live_[A-Za-z0-9_-]{12,}|eyJ[A-Za-z0-9_-]{20,}|-----BEGIN (?:RSA |OPENSSH |EC )?PRIVATE KEY-----)/;
2488
+ z.enum([
2489
+ "system",
2490
+ "resource",
2491
+ "ontology",
2492
+ "policy",
2493
+ "role",
2494
+ "trigger",
2495
+ "humanCheckpoint",
2496
+ "externalResource"
2497
+ ]);
2498
+ var OmTopologyRelationshipKindSchema = z.enum(["triggers", "uses", "approval"]);
2499
+ var OmTopologyNodeRefSchema = z.discriminatedUnion("kind", [
2500
+ z.object({ kind: z.literal("system"), id: ModelIdSchema }),
2501
+ z.object({ kind: z.literal("resource"), id: ResourceIdSchema }),
2502
+ z.object({ kind: z.literal("ontology"), id: OntologyIdSchema }),
2503
+ z.object({ kind: z.literal("policy"), id: ModelIdSchema }),
2504
+ z.object({ kind: z.literal("role"), id: ModelIdSchema }),
2505
+ z.object({ kind: z.literal("trigger"), id: ResourceIdSchema }),
2506
+ z.object({ kind: z.literal("humanCheckpoint"), id: ResourceIdSchema }),
2507
+ z.object({ kind: z.literal("externalResource"), id: ResourceIdSchema })
2508
+ ]);
2509
+ var OmTopologyMetadataSchema = z.record(z.string().trim().min(1).max(120), JsonValueSchema).superRefine((metadata, ctx) => {
2510
+ function visit(value, path) {
2511
+ if (typeof value === "string" && SecretLikeMetadataValueSchema.test(value)) {
2512
+ ctx.addIssue({
2513
+ code: z.ZodIssueCode.custom,
2514
+ path,
2515
+ message: "Topology metadata must not contain secret-like values"
2516
+ });
2517
+ return;
2518
+ }
2519
+ if (Array.isArray(value)) {
2520
+ value.forEach((entry, index) => visit(entry, [...path, index]));
2521
+ return;
2522
+ }
2523
+ if (typeof value !== "object" || value === null) return;
2524
+ Object.entries(value).forEach(([key, entry]) => {
2525
+ if (SecretLikeMetadataKeySchema.test(key)) {
2526
+ ctx.addIssue({
2527
+ code: z.ZodIssueCode.custom,
2528
+ path: [...path, key],
2529
+ message: `Topology metadata key "${key}" looks secret-like`
2530
+ });
2531
+ }
2532
+ visit(entry, [...path, key]);
2533
+ });
2534
+ }
2535
+ visit(metadata, []);
2536
+ });
2537
+ var OmTopologyRelationshipSchema = z.object({
2538
+ from: OmTopologyNodeRefSchema,
2539
+ kind: OmTopologyRelationshipKindSchema,
2540
+ to: OmTopologyNodeRefSchema,
2541
+ systemPath: SystemPathSchema.optional(),
2542
+ required: z.boolean().optional(),
2543
+ metadata: OmTopologyMetadataSchema.optional()
2544
+ });
2545
+ var OmTopologyDomainSchema = z.object({
2546
+ version: z.literal(1).default(1),
2547
+ relationships: z.record(z.string().trim().min(1).max(255), OmTopologyRelationshipSchema).default({})
2548
+ }).default({ version: 1, relationships: {} });
2549
+ var DEFAULT_ORGANIZATION_MODEL_TOPOLOGY = {
2550
+ version: 1,
2551
+ relationships: {}
2552
+ };
1902
2553
  var PolicyIdSchema = ModelIdSchema;
1903
2554
  var PolicyApplicabilitySchema = z.object({
1904
2555
  systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
@@ -1986,7 +2637,9 @@ z.enum([
1986
2637
  "roles",
1987
2638
  "goals",
1988
2639
  "systems",
2640
+ "ontology",
1989
2641
  "resources",
2642
+ "topology",
1990
2643
  "actions",
1991
2644
  "entities",
1992
2645
  "policies",
@@ -2004,7 +2657,9 @@ var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
2004
2657
  roles: { version: 1, lastModified: "2026-05-10" },
2005
2658
  goals: { version: 1, lastModified: "2026-05-10" },
2006
2659
  systems: { version: 1, lastModified: "2026-05-10" },
2660
+ ontology: { version: 1, lastModified: "2026-05-14" },
2007
2661
  resources: { version: 1, lastModified: "2026-05-10" },
2662
+ topology: { version: 1, lastModified: "2026-05-14" },
2008
2663
  actions: { version: 1, lastModified: "2026-05-10" },
2009
2664
  entities: { version: 1, lastModified: "2026-05-10" },
2010
2665
  policies: { version: 1, lastModified: "2026-05-10" },
@@ -2018,7 +2673,9 @@ var OrganizationModelDomainMetadataByDomainSchema = z.object({
2018
2673
  roles: OrganizationModelDomainMetadataSchema,
2019
2674
  goals: OrganizationModelDomainMetadataSchema,
2020
2675
  systems: OrganizationModelDomainMetadataSchema,
2676
+ ontology: OrganizationModelDomainMetadataSchema,
2021
2677
  resources: OrganizationModelDomainMetadataSchema,
2678
+ topology: OrganizationModelDomainMetadataSchema,
2022
2679
  actions: OrganizationModelDomainMetadataSchema,
2023
2680
  entities: OrganizationModelDomainMetadataSchema,
2024
2681
  policies: OrganizationModelDomainMetadataSchema,
@@ -2035,7 +2692,9 @@ var OrganizationModelSchemaBase = z.object({
2035
2692
  roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
2036
2693
  goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
2037
2694
  systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
2695
+ ontology: OntologyScopeSchema.default(DEFAULT_ONTOLOGY_SCOPE),
2038
2696
  resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
2697
+ topology: OmTopologyDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_TOPOLOGY),
2039
2698
  actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
2040
2699
  entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
2041
2700
  policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
@@ -2062,13 +2721,16 @@ function asRoleHolderArray(heldBy) {
2062
2721
  function isKnowledgeKindCompatibleWithTarget(knowledgeKind, targetKind) {
2063
2722
  if (knowledgeKind === "reference") return true;
2064
2723
  if (knowledgeKind === "playbook") {
2065
- return ["system", "resource", "stage", "action"].includes(targetKind);
2724
+ return ["system", "resource", "stage", "action", "ontology"].includes(targetKind);
2066
2725
  }
2067
2726
  if (knowledgeKind === "strategy") {
2068
- return ["system", "goal", "offering", "customer-segment"].includes(targetKind);
2727
+ return ["system", "goal", "offering", "customer-segment", "ontology"].includes(targetKind);
2069
2728
  }
2070
2729
  return false;
2071
2730
  }
2731
+ function isRecord(value) {
2732
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2733
+ }
2072
2734
  var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
2073
2735
  function collectAllSystems(systems, prefix = "", schemaPath = ["systems"]) {
2074
2736
  const result = [];
@@ -2076,8 +2738,11 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2076
2738
  const path = prefix ? `${prefix}.${key}` : key;
2077
2739
  const currentSchemaPath = [...schemaPath, key];
2078
2740
  result.push({ path, schemaPath: currentSchemaPath, system });
2079
- if (system.subsystems !== void 0) {
2080
- result.push(...collectAllSystems(system.subsystems, path, [...currentSchemaPath, "subsystems"]));
2741
+ const childSystems = system.systems ?? system.subsystems;
2742
+ if (childSystems !== void 0) {
2743
+ result.push(
2744
+ ...collectAllSystems(childSystems, path, [...currentSchemaPath, system.systems !== void 0 ? "systems" : "subsystems"])
2745
+ );
2081
2746
  }
2082
2747
  }
2083
2748
  return result;
@@ -2097,7 +2762,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2097
2762
  `System "${system.id}" references unknown parent "${system.parentSystemId}"`
2098
2763
  );
2099
2764
  }
2100
- const hasChildren = Object.keys(system.subsystems ?? {}).length > 0 || allSystems.some((candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes("."));
2765
+ const hasChildren = Object.keys(system.systems ?? system.subsystems ?? {}).length > 0 || allSystems.some((candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes("."));
2101
2766
  const contributesRoutePath = system.ui?.path !== void 0 || system.path !== void 0 || !hasChildren;
2102
2767
  if (contributesRoutePath) {
2103
2768
  const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path);
@@ -2113,7 +2778,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2113
2778
  }
2114
2779
  }
2115
2780
  if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
2116
- const hasEnabledDescendant = Object.values(system.subsystems ?? {}).some(
2781
+ const hasEnabledDescendant = Object.values(system.systems ?? system.subsystems ?? {}).some(
2117
2782
  (candidate) => isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
2118
2783
  ) || allSystems.some(
2119
2784
  (candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
@@ -2358,6 +3023,79 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2358
3023
  const stageIds = /* @__PURE__ */ new Set();
2359
3024
  const actionIds = new Set(Object.keys(model.actions));
2360
3025
  const offeringsById = new Map(Object.entries(model.offerings));
3026
+ const ontologyCompilation = compileOrganizationOntology(model);
3027
+ const ontologyIndexByKind = {
3028
+ object: ontologyCompilation.ontology.objectTypes,
3029
+ link: ontologyCompilation.ontology.linkTypes,
3030
+ action: ontologyCompilation.ontology.actionTypes,
3031
+ catalog: ontologyCompilation.ontology.catalogTypes,
3032
+ event: ontologyCompilation.ontology.eventTypes,
3033
+ interface: ontologyCompilation.ontology.interfaceTypes,
3034
+ "value-type": ontologyCompilation.ontology.valueTypes,
3035
+ property: ontologyCompilation.ontology.sharedProperties,
3036
+ group: ontologyCompilation.ontology.groups,
3037
+ surface: ontologyCompilation.ontology.surfaces
3038
+ };
3039
+ const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)));
3040
+ function topologyTargetExists(ref) {
3041
+ if (ref.kind === "system") return systemsById.has(ref.id);
3042
+ if (ref.kind === "resource") return resourcesById.has(ref.id);
3043
+ if (ref.kind === "ontology") return ontologyIds.has(ref.id);
3044
+ if (ref.kind === "policy") return policiesById.has(ref.id);
3045
+ if (ref.kind === "role") return rolesById.has(ref.id);
3046
+ return true;
3047
+ }
3048
+ Object.entries(model.topology.relationships).forEach(([relationshipId, relationship]) => {
3049
+ ["from", "to"].forEach((side) => {
3050
+ const ref = relationship[side];
3051
+ if (topologyTargetExists(ref)) return;
3052
+ addIssue(
3053
+ ctx,
3054
+ ["topology", "relationships", relationshipId, side],
3055
+ `Topology relationship "${relationshipId}" ${side} references unknown ${ref.kind} "${ref.id}"`
3056
+ );
3057
+ });
3058
+ });
3059
+ const ontologyReferenceKeyKinds = {
3060
+ valueType: "value-type",
3061
+ catalogType: "catalog",
3062
+ objectType: "object",
3063
+ eventType: "event",
3064
+ actionType: "action",
3065
+ linkType: "link",
3066
+ interfaceType: "interface",
3067
+ propertyType: "property",
3068
+ groupType: "group",
3069
+ surfaceType: "surface",
3070
+ stepCatalog: "catalog"
3071
+ };
3072
+ function validateKnownOntologyReferences(ownerId, value, path, seen = /* @__PURE__ */ new WeakSet()) {
3073
+ if (Array.isArray(value)) {
3074
+ value.forEach((entry, index) => validateKnownOntologyReferences(ownerId, entry, [...path, index], seen));
3075
+ return;
3076
+ }
3077
+ if (!isRecord(value)) return;
3078
+ if (seen.has(value)) return;
3079
+ seen.add(value);
3080
+ Object.entries(value).forEach(([key, entry]) => {
3081
+ const expectedKind = ontologyReferenceKeyKinds[key];
3082
+ if (expectedKind !== void 0) {
3083
+ if (typeof entry !== "string") {
3084
+ addIssue(ctx, [...path, key], `Ontology record "${ownerId}" ${key} must be an ontology ID string`);
3085
+ } else if (ontologyIndexByKind[expectedKind][entry] === void 0) {
3086
+ addIssue(
3087
+ ctx,
3088
+ [...path, key],
3089
+ `Ontology record "${ownerId}" ${key} references unknown ${expectedKind} ontology ID "${entry}"`
3090
+ );
3091
+ }
3092
+ }
3093
+ validateKnownOntologyReferences(ownerId, entry, [...path, key], seen);
3094
+ });
3095
+ }
3096
+ for (const { id, record } of listResolvedOntologyRecords(ontologyCompilation.ontology)) {
3097
+ validateKnownOntologyReferences(id, record, record.origin.path);
3098
+ }
2361
3099
  Object.values(model.policies).forEach((policy) => {
2362
3100
  policy.appliesTo.systemIds.forEach((systemId, systemIndex) => {
2363
3101
  if (!systemsById.has(systemId)) {
@@ -2411,6 +3149,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2411
3149
  if (kind === "goal") return goalsById.has(id);
2412
3150
  if (kind === "customer-segment") return segmentsById.has(id);
2413
3151
  if (kind === "offering") return offeringsById.has(id);
3152
+ if (kind === "ontology") return ontologyIds.has(id);
2414
3153
  return false;
2415
3154
  }
2416
3155
  Object.entries(model.knowledge).forEach(([nodeId2, node]) => {
@@ -2454,6 +3193,34 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2454
3193
  );
2455
3194
  }
2456
3195
  });
3196
+ function validateResourceOntologyBinding(resourceId, bindingKey, expectedKind, ids) {
3197
+ const ontologyIds2 = ids === void 0 ? [] : Array.isArray(ids) ? ids : [ids];
3198
+ ontologyIds2.forEach((ontologyId, ontologyIndex) => {
3199
+ if (ontologyIndexByKind[expectedKind][ontologyId] === void 0) {
3200
+ addIssue(
3201
+ ctx,
3202
+ [
3203
+ "resources",
3204
+ resourceId,
3205
+ "ontology",
3206
+ bindingKey,
3207
+ ...Array.isArray(ids) ? [ontologyIndex] : []
3208
+ ],
3209
+ `Resource "${resourceId}" ontology binding "${bindingKey}" references unknown ${expectedKind} ontology ID "${ontologyId}"`
3210
+ );
3211
+ }
3212
+ });
3213
+ }
3214
+ Object.values(model.resources).forEach((resource) => {
3215
+ const binding = resource.ontology;
3216
+ if (binding === void 0) return;
3217
+ validateResourceOntologyBinding(resource.id, "actions", "action", binding.actions);
3218
+ validateResourceOntologyBinding(resource.id, "primaryAction", "action", binding.primaryAction);
3219
+ validateResourceOntologyBinding(resource.id, "reads", "object", binding.reads);
3220
+ validateResourceOntologyBinding(resource.id, "writes", "object", binding.writes);
3221
+ validateResourceOntologyBinding(resource.id, "usesCatalogs", "catalog", binding.usesCatalogs);
3222
+ validateResourceOntologyBinding(resource.id, "emits", "event", binding.emits);
3223
+ });
2457
3224
  Object.values(model.roles).forEach((role) => {
2458
3225
  if (role.heldBy === void 0) return;
2459
3226
  asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
@@ -2488,11 +3255,13 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2488
3255
  });
2489
3256
  });
2490
3257
  function validateSystemContent(system, systemPath) {
3258
+ const childSystems = system.systems ?? system.subsystems;
3259
+ const childKey = system.systems !== void 0 ? "systems" : "subsystems";
2491
3260
  const content = system.content;
2492
3261
  if (content === void 0 || Object.keys(content).length === 0) {
2493
- if (system.subsystems !== void 0) {
2494
- Object.entries(system.subsystems).forEach(([childKey, child]) => {
2495
- validateSystemContent(child, [...systemPath, "subsystems", childKey]);
3262
+ if (childSystems !== void 0) {
3263
+ Object.entries(childSystems).forEach(([childLocalId, child]) => {
3264
+ validateSystemContent(child, [...systemPath, childKey, childLocalId]);
2496
3265
  });
2497
3266
  }
2498
3267
  return;
@@ -2548,15 +3317,18 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2548
3317
  }
2549
3318
  }
2550
3319
  });
2551
- if (system.subsystems !== void 0) {
2552
- Object.entries(system.subsystems).forEach(([childKey, child]) => {
2553
- validateSystemContent(child, [...systemPath, "subsystems", childKey]);
3320
+ if (childSystems !== void 0) {
3321
+ Object.entries(childSystems).forEach(([childLocalId, child]) => {
3322
+ validateSystemContent(child, [...systemPath, childKey, childLocalId]);
2554
3323
  });
2555
3324
  }
2556
3325
  }
2557
3326
  Object.entries(model.systems).forEach(([systemKey, system]) => {
2558
3327
  validateSystemContent(system, ["systems", systemKey]);
2559
3328
  });
3329
+ for (const diagnostic of ontologyCompilation.diagnostics) {
3330
+ addIssue(ctx, diagnostic.path, diagnostic.message);
3331
+ }
2560
3332
  });
2561
3333
 
2562
3334
  // ../core/src/organization-model/graph/schema.ts
@@ -2577,6 +3349,7 @@ var OrganizationGraphNodeKindSchema = z.enum([
2577
3349
  "surface",
2578
3350
  "navigation-group",
2579
3351
  // Phase 3 preview — Phase 4 populates via graph projection of system.content entries.
3352
+ "ontology",
2580
3353
  "content-node"
2581
3354
  ]);
2582
3355
  var OrganizationGraphEdgeKindSchema = z.enum([
@@ -2590,24 +3363,30 @@ var OrganizationGraphEdgeKindSchema = z.enum([
2590
3363
  "emits",
2591
3364
  "originates_from",
2592
3365
  "triggers",
3366
+ "approval",
2593
3367
  "applies_to",
2594
- "effects"
3368
+ "effects",
3369
+ "actions",
3370
+ "reads",
3371
+ "writes",
3372
+ "uses_catalog"
2595
3373
  ]);
2596
3374
  var OrganizationGraphNodeSchema = z.object({
2597
- id: z.string().trim().min(1).max(200),
3375
+ id: z.string().trim().min(1).max(400),
2598
3376
  kind: OrganizationGraphNodeKindSchema,
2599
3377
  label: LabelSchema,
2600
- sourceId: z.string().trim().min(1).max(255).optional(),
3378
+ sourceId: z.string().trim().min(1).max(400).optional(),
2601
3379
  description: DescriptionSchema.optional(),
2602
3380
  icon: IconNameSchema.optional(),
2603
3381
  enabled: z.boolean().optional(),
3382
+ ontologyKind: z.string().trim().min(1).max(80).optional(),
2604
3383
  resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint", "script"]).optional()
2605
3384
  });
2606
3385
  var OrganizationGraphEdgeSchema = z.object({
2607
- id: z.string().trim().min(1).max(250),
3386
+ id: z.string().trim().min(1).max(900),
2608
3387
  kind: OrganizationGraphEdgeKindSchema,
2609
- sourceId: z.string().trim().min(1).max(200),
2610
- targetId: z.string().trim().min(1).max(200),
3388
+ sourceId: z.string().trim().min(1).max(400),
3389
+ targetId: z.string().trim().min(1).max(400),
2611
3390
  label: z.string().trim().min(1).max(120).optional(),
2612
3391
  relationshipType: z.enum(["triggers", "uses", "approval"]).optional()
2613
3392
  });
@@ -2668,7 +3447,7 @@ function getAllBuildTemplates(model) {
2668
3447
  label: s.label ?? stepLocalId,
2669
3448
  ...s.description ? { description: s.description } : {},
2670
3449
  // Pass through all data fields — template-step payload is richer than Pipeline;
2671
- // Wave 2 authors the canonical shape; Wave 4 verifies round-trip fidelity.
3450
+ // Bridge readers preserve the historical shape for round-trip fidelity.
2672
3451
  ...sd
2673
3452
  };
2674
3453
  });
@@ -2832,6 +3611,20 @@ function invocationLabel(invocation) {
2832
3611
  function eventNodeId(eventId) {
2833
3612
  return nodeId("event", eventId);
2834
3613
  }
3614
+ function ontologyLabel(id, label) {
3615
+ return label ?? parseOntologyId(id).localId;
3616
+ }
3617
+ function pushOntologyBindingEdges(edges, edgeIds, resourceNodeId, kind, ids) {
3618
+ ids?.forEach((ontologyId) => {
3619
+ const targetId = ontologyGraphNodeId(ontologyId);
3620
+ pushUniqueEdge(edges, edgeIds, {
3621
+ id: edgeId(kind, resourceNodeId, targetId),
3622
+ kind,
3623
+ sourceId: resourceNodeId,
3624
+ targetId
3625
+ });
3626
+ });
3627
+ }
2835
3628
  function buildResourceEventDescriptor(resourceId, emission) {
2836
3629
  return {
2837
3630
  ...emission,
@@ -2879,6 +3672,7 @@ function buildOrganizationGraph(input) {
2879
3672
  const organizationModelResourceIds = new Set(Object.keys(organizationModel.resources));
2880
3673
  const actionIdsByInvocation = /* @__PURE__ */ new Map();
2881
3674
  const projectedEventNodeIdsByEventId = /* @__PURE__ */ new Map();
3675
+ const ontologyCompilation = compileOrganizationOntology(organizationModel);
2882
3676
  const organizationNode = {
2883
3677
  id: nodeId("organization"),
2884
3678
  kind: "organization",
@@ -2893,6 +3687,32 @@ function buildOrganizationGraph(input) {
2893
3687
  }
2894
3688
  const validSystemRefs = new Set(systemPathByRef.keys());
2895
3689
  const systemNodeId = (systemRef) => nodeId("system", systemPathByRef.get(systemRef) ?? systemRef);
3690
+ function topologyNodeId(ref) {
3691
+ if (ref.kind === "system") return systemNodeId(ref.id);
3692
+ if (ref.kind === "resource") return nodeId("resource", ref.id);
3693
+ if (ref.kind === "ontology") return ontologyGraphNodeId(ref.id);
3694
+ if (ref.kind === "policy") return nodeId("policy", ref.id);
3695
+ if (ref.kind === "role") return nodeId("role", ref.id);
3696
+ return nodeId("resource", ref.id);
3697
+ }
3698
+ function ensureTopologyNode(ref) {
3699
+ const id = topologyNodeId(ref);
3700
+ if (nodeIds.has(id)) return id;
3701
+ if (ref.kind === "resource") {
3702
+ ensureResourceNode(nodes, nodeIds, resourceNodesById, ref.id);
3703
+ return id;
3704
+ }
3705
+ if (ref.kind === "trigger" || ref.kind === "humanCheckpoint" || ref.kind === "externalResource") {
3706
+ pushUniqueNode(nodes, nodeIds, {
3707
+ id,
3708
+ kind: "resource",
3709
+ label: ref.id,
3710
+ sourceId: ref.id,
3711
+ resourceType: ref.kind === "trigger" ? "trigger" : ref.kind === "humanCheckpoint" ? "human_checkpoint" : "external"
3712
+ });
3713
+ }
3714
+ return id;
3715
+ }
2896
3716
  for (const { path, system } of systemsWithPaths.sort((a, b) => a.path.localeCompare(b.path))) {
2897
3717
  const id = nodeId("system", path);
2898
3718
  pushUniqueNode(nodes, nodeIds, {
@@ -2920,6 +3740,78 @@ function buildOrganizationGraph(input) {
2920
3740
  });
2921
3741
  }
2922
3742
  }
3743
+ for (const { id: ontologyId, kind, record } of listResolvedOntologyRecords(ontologyCompilation.ontology).sort(
3744
+ (a, b) => a.id.localeCompare(b.id)
3745
+ )) {
3746
+ const id = ontologyGraphNodeId(ontologyId);
3747
+ const parsedId = parseOntologyId(ontologyId);
3748
+ pushUniqueNode(nodes, nodeIds, {
3749
+ id,
3750
+ kind: "ontology",
3751
+ label: ontologyLabel(ontologyId, record.label),
3752
+ sourceId: ontologyId,
3753
+ description: record.description,
3754
+ ontologyKind: kind
3755
+ });
3756
+ const ownerSystemId = record.ownerSystemId ?? (parsedId.isGlobal ? void 0 : parsedId.scope);
3757
+ if (ownerSystemId !== void 0 && validSystemRefs.has(ownerSystemId)) {
3758
+ pushUniqueEdge(edges, edgeIds, {
3759
+ id: edgeId("contains", systemNodeId(ownerSystemId), id, `ontology-${kind}`),
3760
+ kind: "contains",
3761
+ sourceId: systemNodeId(ownerSystemId),
3762
+ targetId: id
3763
+ });
3764
+ } else {
3765
+ pushUniqueEdge(edges, edgeIds, {
3766
+ id: edgeId("contains", organizationNode.id, id, `ontology-${kind}`),
3767
+ kind: "contains",
3768
+ sourceId: organizationNode.id,
3769
+ targetId: id
3770
+ });
3771
+ }
3772
+ if (kind === "link") {
3773
+ const link = record;
3774
+ pushUniqueEdge(edges, edgeIds, {
3775
+ id: edgeId("links", ontologyGraphNodeId(link.from), ontologyGraphNodeId(link.to), ontologyId),
3776
+ kind: "links",
3777
+ sourceId: ontologyGraphNodeId(link.from),
3778
+ targetId: ontologyGraphNodeId(link.to),
3779
+ label: link.label ?? parsedId.localId
3780
+ });
3781
+ }
3782
+ if (kind === "action") {
3783
+ const action = record;
3784
+ for (const targetOntologyId of action.actsOn ?? []) {
3785
+ pushUniqueEdge(edges, edgeIds, {
3786
+ id: edgeId("affects", id, ontologyGraphNodeId(targetOntologyId), ontologyId),
3787
+ kind: "affects",
3788
+ sourceId: id,
3789
+ targetId: ontologyGraphNodeId(targetOntologyId)
3790
+ });
3791
+ }
3792
+ }
3793
+ if (kind === "catalog") {
3794
+ const catalog = record;
3795
+ if (catalog.appliesTo === void 0) continue;
3796
+ pushUniqueEdge(edges, edgeIds, {
3797
+ id: edgeId("applies_to", id, ontologyGraphNodeId(catalog.appliesTo), ontologyId),
3798
+ kind: "applies_to",
3799
+ sourceId: id,
3800
+ targetId: ontologyGraphNodeId(catalog.appliesTo)
3801
+ });
3802
+ }
3803
+ if (kind === "group") {
3804
+ const group = record;
3805
+ for (const memberOntologyId of group.members ?? []) {
3806
+ pushUniqueEdge(edges, edgeIds, {
3807
+ id: edgeId("contains", id, ontologyGraphNodeId(memberOntologyId), ontologyId),
3808
+ kind: "contains",
3809
+ sourceId: id,
3810
+ targetId: ontologyGraphNodeId(memberOntologyId)
3811
+ });
3812
+ }
3813
+ }
3814
+ }
2923
3815
  for (const role of Object.values(organizationModel.roles).sort((a, b) => a.id.localeCompare(b.id))) {
2924
3816
  const id = nodeId("role", role.id);
2925
3817
  pushUniqueNode(nodes, nodeIds, {
@@ -2971,7 +3863,7 @@ function buildOrganizationGraph(input) {
2971
3863
  targetId: id
2972
3864
  });
2973
3865
  for (const link of node.links) {
2974
- const targetId = link.target.kind === "system" ? systemNodeId(link.target.id) : link.nodeId;
3866
+ const targetId = link.target.kind === "system" ? systemNodeId(link.target.id) : link.target.kind === "ontology" ? ontologyGraphNodeId(link.target.id) : link.nodeId;
2975
3867
  pushUniqueEdge(edges, edgeIds, {
2976
3868
  id: edgeId("governs", id, targetId),
2977
3869
  kind: "governs",
@@ -3136,6 +4028,11 @@ function buildOrganizationGraph(input) {
3136
4028
  targetId: resourceNode.id
3137
4029
  });
3138
4030
  }
4031
+ pushOntologyBindingEdges(edges, edgeIds, resourceNode.id, "actions", resource.ontology?.actions);
4032
+ pushOntologyBindingEdges(edges, edgeIds, resourceNode.id, "reads", resource.ontology?.reads);
4033
+ pushOntologyBindingEdges(edges, edgeIds, resourceNode.id, "writes", resource.ontology?.writes);
4034
+ pushOntologyBindingEdges(edges, edgeIds, resourceNode.id, "uses_catalog", resource.ontology?.usesCatalogs);
4035
+ pushOntologyBindingEdges(edges, edgeIds, resourceNode.id, "emits", resource.ontology?.emits);
3139
4036
  if (resource.kind === "workflow" || resource.kind === "agent") {
3140
4037
  for (const emission of resource.emits ?? []) {
3141
4038
  pushEventProjection(
@@ -3265,6 +4162,19 @@ function buildOrganizationGraph(input) {
3265
4162
  }
3266
4163
  }
3267
4164
  }
4165
+ for (const [relationshipId, relationship] of Object.entries(organizationModel.topology.relationships).sort(
4166
+ ([a], [b]) => a.localeCompare(b)
4167
+ )) {
4168
+ const sourceId = ensureTopologyNode(relationship.from);
4169
+ const targetId = ensureTopologyNode(relationship.to);
4170
+ pushUniqueEdge(edges, edgeIds, {
4171
+ id: edgeId(relationship.kind, sourceId, targetId, `topology-${relationshipId}`),
4172
+ kind: relationship.kind,
4173
+ sourceId,
4174
+ targetId,
4175
+ relationshipType: relationship.kind
4176
+ });
4177
+ }
3268
4178
  for (const segment of Object.values(organizationModel.customers).sort(
3269
4179
  (a, b) => a.order - b.order || a.id.localeCompare(b.id)
3270
4180
  )) {
@@ -3510,14 +4420,14 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
3510
4420
  label: "Dashboard",
3511
4421
  path: "/",
3512
4422
  surfaceType: "dashboard",
3513
- icon: "feature.dashboard",
4423
+ icon: "dashboard",
3514
4424
  order: 10,
3515
4425
  targets: { systems: ["dashboard"] }
3516
4426
  },
3517
4427
  business: {
3518
4428
  type: "group",
3519
4429
  label: "Business",
3520
- icon: "feature.business",
4430
+ icon: "business",
3521
4431
  order: 20,
3522
4432
  children: {
3523
4433
  sales: {
@@ -3525,7 +4435,7 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
3525
4435
  label: "Sales",
3526
4436
  path: "/sales",
3527
4437
  surfaceType: "page",
3528
- icon: "feature.sales",
4438
+ icon: "sales",
3529
4439
  order: 10,
3530
4440
  targets: { systems: ["sales"] }
3531
4441
  },
@@ -3534,7 +4444,7 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
3534
4444
  label: "Clients",
3535
4445
  path: "/clients",
3536
4446
  surfaceType: "list",
3537
- icon: "feature.projects",
4447
+ icon: "projects",
3538
4448
  order: 20,
3539
4449
  targets: { systems: ["clients"] }
3540
4450
  },
@@ -3543,7 +4453,7 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
3543
4453
  label: "Projects",
3544
4454
  path: "/projects",
3545
4455
  surfaceType: "page",
3546
- icon: "feature.projects",
4456
+ icon: "projects",
3547
4457
  order: 30,
3548
4458
  targets: { systems: ["projects"] }
3549
4459
  }
@@ -3552,7 +4462,7 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
3552
4462
  operations: {
3553
4463
  type: "group",
3554
4464
  label: "Operations",
3555
- icon: "feature.operations",
4465
+ icon: "operations",
3556
4466
  order: 30,
3557
4467
  children: {
3558
4468
  "operations-overview": {
@@ -3600,7 +4510,7 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
3600
4510
  monitoring: {
3601
4511
  type: "group",
3602
4512
  label: "Monitoring",
3603
- icon: "feature.monitoring",
4513
+ icon: "monitoring",
3604
4514
  order: 40,
3605
4515
  children: {
3606
4516
  "monitoring-overview": {
@@ -3662,36 +4572,19 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
3662
4572
  }
3663
4573
  },
3664
4574
  knowledge: {
3665
- type: "group",
3666
- label: "Knowledge",
3667
- icon: "feature.knowledge",
3668
- order: 50,
3669
- children: {
3670
- "knowledge-base": {
3671
- type: "surface",
3672
- label: "Knowledge Base",
3673
- path: "/knowledge",
3674
- surfaceType: "page",
3675
- order: 10,
3676
- targets: { systems: ["knowledge.base"] }
3677
- },
3678
- "knowledge-command-view": {
3679
- type: "surface",
3680
- label: "Command View",
3681
- path: "/knowledge/command-view",
3682
- surfaceType: "graph",
3683
- order: 20,
3684
- targets: { systems: ["knowledge.command-view"] },
3685
- devOnly: true
3686
- }
3687
- }
4575
+ type: "surface",
4576
+ label: "Knowledge Base",
4577
+ path: "/knowledge",
4578
+ surfaceType: "page",
4579
+ icon: "knowledge",
4580
+ order: 50
3688
4581
  }
3689
4582
  },
3690
4583
  bottom: {
3691
4584
  settings: {
3692
4585
  type: "group",
3693
4586
  label: "Settings",
3694
- icon: "feature.settings",
4587
+ icon: "settings",
3695
4588
  order: 10,
3696
4589
  children: {
3697
4590
  "settings-account": {
@@ -3763,7 +4656,7 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
3763
4656
  admin: {
3764
4657
  type: "group",
3765
4658
  label: "Admin",
3766
- icon: "feature.admin",
4659
+ icon: "admin",
3767
4660
  order: 20,
3768
4661
  children: {
3769
4662
  "admin-dashboard": {
@@ -3843,7 +4736,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
3843
4736
  enabled: true,
3844
4737
  lifecycle: "active",
3845
4738
  path: "/",
3846
- icon: "feature.dashboard"
4739
+ icon: "dashboard"
3847
4740
  },
3848
4741
  platform: {
3849
4742
  id: "platform",
@@ -3853,7 +4746,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
3853
4746
  enabled: true,
3854
4747
  lifecycle: "active",
3855
4748
  color: "cyan",
3856
- icon: "feature.platform"
4749
+ icon: "platform"
3857
4750
  },
3858
4751
  finance: {
3859
4752
  id: "finance",
@@ -3863,7 +4756,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
3863
4756
  enabled: true,
3864
4757
  lifecycle: "active",
3865
4758
  color: "green",
3866
- icon: "feature.finance"
4759
+ icon: "finance"
3867
4760
  },
3868
4761
  sales: {
3869
4762
  id: "sales",
@@ -3873,7 +4766,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
3873
4766
  enabled: true,
3874
4767
  lifecycle: "active",
3875
4768
  color: "blue",
3876
- icon: "feature.sales",
4769
+ icon: "sales",
3877
4770
  path: "/sales"
3878
4771
  },
3879
4772
  "sales.crm": {
@@ -3883,8 +4776,12 @@ var DEFAULT_ORGANIZATION_MODEL = {
3883
4776
  description: "Relationship pipeline and deal management",
3884
4777
  enabled: true,
3885
4778
  lifecycle: "active",
4779
+ actions: Object.values(CRM_ACTION_ENTRIES).map((action) => ({
4780
+ actionId: action.id,
4781
+ intent: "exposes"
4782
+ })),
3886
4783
  color: "blue",
3887
- icon: "feature.crm",
4784
+ icon: "crm",
3888
4785
  path: "/crm"
3889
4786
  },
3890
4787
  "sales.lead-gen": {
@@ -3894,12 +4791,12 @@ var DEFAULT_ORGANIZATION_MODEL = {
3894
4791
  description: "Prospecting, qualification, and outreach preparation",
3895
4792
  enabled: true,
3896
4793
  lifecycle: "active",
3897
- actions: Object.values(DEFAULT_ORGANIZATION_MODEL_ACTIONS).map((action) => ({
4794
+ actions: Object.values(LEAD_GEN_ACTION_ENTRIES).map((action) => ({
3898
4795
  actionId: action.id,
3899
4796
  intent: "exposes"
3900
4797
  })),
3901
4798
  color: "cyan",
3902
- icon: "feature.lead-gen",
4799
+ icon: "lead-gen",
3903
4800
  path: "/lead-gen"
3904
4801
  },
3905
4802
  projects: {
@@ -3910,7 +4807,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
3910
4807
  enabled: true,
3911
4808
  lifecycle: "active",
3912
4809
  color: "orange",
3913
- icon: "feature.projects",
4810
+ icon: "projects",
3914
4811
  path: "/projects"
3915
4812
  },
3916
4813
  clients: {
@@ -3921,7 +4818,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
3921
4818
  enabled: true,
3922
4819
  lifecycle: "active",
3923
4820
  color: "orange",
3924
- icon: "feature.projects",
4821
+ icon: "projects",
3925
4822
  path: "/clients"
3926
4823
  },
3927
4824
  operations: {
@@ -3932,7 +4829,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
3932
4829
  enabled: true,
3933
4830
  lifecycle: "active",
3934
4831
  color: "violet",
3935
- icon: "feature.operations"
4832
+ icon: "operations"
3936
4833
  },
3937
4834
  "knowledge.command-view": {
3938
4835
  id: "knowledge.command-view",
@@ -3998,7 +4895,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
3998
4895
  enabled: true,
3999
4896
  lifecycle: "active",
4000
4897
  path: "/monitoring/calendar",
4001
- icon: "feature.calendar"
4898
+ icon: "calendar"
4002
4899
  },
4003
4900
  "monitoring.activity-log": {
4004
4901
  id: "monitoring.activity-log",
@@ -4054,7 +4951,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
4054
4951
  label: "Settings",
4055
4952
  enabled: true,
4056
4953
  lifecycle: "active",
4057
- icon: "feature.settings"
4954
+ icon: "settings"
4058
4955
  },
4059
4956
  "settings.account": {
4060
4957
  id: "settings.account",
@@ -4127,7 +5024,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
4127
5024
  enabled: true,
4128
5025
  lifecycle: "active",
4129
5026
  path: "/admin",
4130
- icon: "feature.admin",
5027
+ icon: "admin",
4131
5028
  requiresAdmin: true
4132
5029
  },
4133
5030
  "admin.system-health": {
@@ -4177,7 +5074,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
4177
5074
  enabled: true,
4178
5075
  lifecycle: "active",
4179
5076
  path: "/archive",
4180
- icon: "feature.archive",
5077
+ icon: "archive",
4181
5078
  devOnly: true
4182
5079
  },
4183
5080
  "archive.agent-chat": {
@@ -4212,7 +5109,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
4212
5109
  enabled: true,
4213
5110
  lifecycle: "active",
4214
5111
  color: "teal",
4215
- icon: "feature.knowledge"
5112
+ icon: "knowledge"
4216
5113
  },
4217
5114
  "knowledge.base": {
4218
5115
  id: "knowledge.base",
@@ -4223,11 +5120,14 @@ var DEFAULT_ORGANIZATION_MODEL = {
4223
5120
  path: "/knowledge"
4224
5121
  }
4225
5122
  },
5123
+ ontology: DEFAULT_ONTOLOGY_SCOPE,
4226
5124
  resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
5125
+ topology: DEFAULT_ORGANIZATION_MODEL_TOPOLOGY,
4227
5126
  actions: DEFAULT_ORGANIZATION_MODEL_ACTIONS,
4228
5127
  entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
4229
5128
  policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
4230
- // Phase 4 (D1): statuses top-level field removed; status data lives in system.content.
5129
+ // Phase 4 (D1): statuses top-level field removed; bridge status mirrors may
5130
+ // still project from System.content, but primary authoring belongs in ontology.
4231
5131
  knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
4232
5132
  };
4233
5133
 
@@ -4235,6 +5135,31 @@ var DEFAULT_ORGANIZATION_MODEL = {
4235
5135
  function isPlainObject(value) {
4236
5136
  return typeof value === "object" && value !== null && !Array.isArray(value);
4237
5137
  }
5138
+ function collectNestedSystemPaths(systems, prefix = "") {
5139
+ const paths = /* @__PURE__ */ new Set();
5140
+ for (const [key, value] of Object.entries(systems)) {
5141
+ if (!isPlainObject(value)) continue;
5142
+ const path = prefix ? `${prefix}.${key}` : key;
5143
+ for (const childKey of ["systems", "subsystems"]) {
5144
+ const childSystems = value[childKey];
5145
+ if (!isPlainObject(childSystems)) continue;
5146
+ for (const childPath of collectNestedSystemPaths(childSystems, path)) {
5147
+ paths.add(childPath);
5148
+ }
5149
+ }
5150
+ if (prefix !== "") {
5151
+ paths.add(path);
5152
+ }
5153
+ }
5154
+ return paths;
5155
+ }
5156
+ function pruneFlatSystemDescendantCollisions(base, override) {
5157
+ const result = { ...base };
5158
+ for (const nestedPath of collectNestedSystemPaths(override)) {
5159
+ delete result[nestedPath];
5160
+ }
5161
+ return result;
5162
+ }
4238
5163
  function deepMerge(base, override) {
4239
5164
  if (override === void 0) {
4240
5165
  return base;
@@ -4249,12 +5174,18 @@ function deepMerge(base, override) {
4249
5174
  for (const [key, value] of Object.entries(override)) {
4250
5175
  if (value === void 0) continue;
4251
5176
  const existing = result[key];
5177
+ if (key === "systems" && isPlainObject(existing) && isPlainObject(value)) {
5178
+ result[key] = deepMerge(pruneFlatSystemDescendantCollisions(existing, value), value);
5179
+ continue;
5180
+ }
4252
5181
  result[key] = isPlainObject(existing) && isPlainObject(value) ? deepMerge(existing, value) : value;
4253
5182
  }
4254
5183
  return result;
4255
5184
  }
4256
- function resolveOrganizationModel(override, organizationId) {
4257
- const merged = deepMerge(DEFAULT_ORGANIZATION_MODEL, override);
5185
+ function resolveOrganizationModel(override, organizationIdOrOptions, options) {
5186
+ const resolvedOptions = typeof organizationIdOrOptions === "object" ? organizationIdOrOptions : options;
5187
+ const mergeDefaults = resolvedOptions?.mergeDefaults ?? true;
5188
+ const merged = mergeDefaults ? deepMerge(DEFAULT_ORGANIZATION_MODEL, override) : override ?? {};
4258
5189
  return OrganizationModelSchema.parse(merged);
4259
5190
  }
4260
5191
 
@@ -4339,4 +5270,4 @@ function projectOrganizationSurfaces(model) {
4339
5270
  });
4340
5271
  }
4341
5272
 
4342
- export { ActionSchema, AgentResourceEntrySchema, CRM_DISCOVERY_BOOKING_CANCELLED_STATE, CRM_DISCOVERY_LINK_SENT_STATE, CRM_DISCOVERY_NUDGING_STATE, CRM_DISCOVERY_REPLIED_STATE, CRM_PIPELINE_DEFINITION, CRM_PRIORITY_BUCKETS, DEFAULT_CRM_PRIORITY_RULE_CONFIG, EntitySchema, IdentityDomainSchema, IntegrationResourceEntrySchema, LEAD_GEN_PIPELINE_DEFINITIONS, LEAD_GEN_STAGE_CATALOG, PROJECTS_VIEW_ACTION_ID, PROSPECTING_STEPS, PolicySchema, RoleSchema, SalesStageSchema, ScriptResourceEntrySchema, SurfaceDefinitionSchema, SystemEntrySchema, WorkflowResourceEntrySchema, ancestorsOf, buildOrganizationGraph, childrenOf, defaultPathFor, devOnlyFor, findById, findByPath, findPipeline, getContent, getResourcesForSystem, getSortedSidebarEntries, getSystem, getSystemAncestors, listAllSystems, lookupContentType, parentOf, projectOrganizationSurfaces, requiresAdminFor, resolveOrganizationModel, topLevel };
5273
+ export { ActionSchema, AgentResourceEntrySchema, CRM_DISCOVERY_BOOKING_CANCELLED_STATE, CRM_DISCOVERY_LINK_SENT_STATE, CRM_DISCOVERY_NUDGING_STATE, CRM_DISCOVERY_REPLIED_STATE, CRM_PIPELINE_DEFINITION, CRM_PRIORITY_BUCKETS, DEFAULT_CRM_PRIORITY_RULE_CONFIG, DEFAULT_ORGANIZATION_MODEL, EntitySchema, IdentityDomainSchema, IntegrationResourceEntrySchema, LEAD_GEN_PIPELINE_DEFINITIONS, LEAD_GEN_STAGE_CATALOG, OntologyIdSchema, PROJECTS_VIEW_ACTION_ID, PROSPECTING_STEPS, PolicySchema, RoleSchema, SalesStageSchema, ScriptResourceEntrySchema, SurfaceDefinitionSchema, SystemEntrySchema, WorkflowResourceEntrySchema, ancestorsOf, buildOrganizationGraph, childrenOf, compileOrganizationOntology, defaultPathFor, devOnlyFor, findById, findByPath, findPipeline, formatOntologyId, getContent, getResourcesForSystem, getSortedSidebarEntries, getSystem, getSystemAncestors, listAllSystems, lookupContentType, ontologyGraphNodeId, parentOf, parseOntologyId, projectOrganizationSurfaces, requiresAdminFor, resolveOrganizationModel, resolveSystemConfig, topLevel };