@elevasis/sdk 1.21.0 → 1.22.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 (160) hide show
  1. package/dist/cli.cjs +1239 -173
  2. package/dist/index.d.ts +1752 -464
  3. package/dist/index.js +3477 -143
  4. package/dist/node/index.d.ts +1 -0
  5. package/dist/node/index.js +19 -1
  6. package/dist/test-utils/index.d.ts +1188 -127
  7. package/dist/test-utils/index.js +3359 -152
  8. package/dist/worker/index.js +3148 -80
  9. package/package.json +2 -2
  10. package/reference/claude-config/hooks/post-edit-validate.mjs +98 -98
  11. package/reference/claude-config/hooks/scaffold-registry-reminder.mjs +188 -188
  12. package/reference/claude-config/hooks/tool-failure-recovery.mjs +73 -73
  13. package/reference/claude-config/registries/graph-skills.json +4 -4
  14. package/reference/claude-config/registries/knowledge-flags.json +0 -2
  15. package/reference/claude-config/rules/active-change-index.md +80 -80
  16. package/reference/claude-config/rules/agent-start-here.md +277 -277
  17. package/reference/claude-config/rules/deployment.md +57 -57
  18. package/reference/claude-config/rules/error-handling.md +56 -56
  19. package/reference/claude-config/rules/execution.md +40 -40
  20. package/reference/claude-config/rules/frontend.md +4 -4
  21. package/reference/claude-config/rules/observability.md +31 -31
  22. package/reference/claude-config/rules/operations.md +29 -17
  23. package/reference/claude-config/rules/organization-model.md +113 -81
  24. package/reference/claude-config/rules/organization-os.md +115 -113
  25. package/reference/claude-config/rules/package-taxonomy.md +33 -33
  26. package/reference/claude-config/rules/platform.md +42 -42
  27. package/reference/claude-config/rules/shared-types.md +49 -46
  28. package/reference/claude-config/rules/task-tracking.md +47 -47
  29. package/reference/claude-config/rules/ui.md +200 -200
  30. package/reference/claude-config/rules/vibe.md +235 -235
  31. package/reference/claude-config/scripts/statusline-command.js +18 -18
  32. package/reference/claude-config/settings.json +34 -34
  33. package/reference/claude-config/skills/deploy/{SKILL.md → skill.md} +156 -156
  34. package/reference/claude-config/skills/dsp/SKILL.md +66 -66
  35. package/reference/claude-config/skills/elevasis/SKILL.md +235 -235
  36. package/reference/claude-config/skills/explore/SKILL.md +6 -6
  37. package/reference/claude-config/skills/git-sync/SKILL.md +126 -126
  38. package/reference/claude-config/skills/knowledge/SKILL.md +314 -299
  39. package/reference/claude-config/skills/knowledge/operations/codify-level-a.md +100 -100
  40. package/reference/claude-config/skills/knowledge/operations/codify-level-b.md +159 -159
  41. package/reference/claude-config/skills/knowledge/operations/customers.md +109 -109
  42. package/reference/claude-config/skills/knowledge/operations/features.md +76 -76
  43. package/reference/claude-config/skills/knowledge/operations/goals.md +118 -118
  44. package/reference/claude-config/skills/knowledge/operations/identity.md +93 -93
  45. package/reference/claude-config/skills/knowledge/operations/labels.md +94 -94
  46. package/reference/claude-config/skills/knowledge/operations/offerings.md +109 -109
  47. package/reference/claude-config/skills/knowledge/operations/roles.md +99 -99
  48. package/reference/claude-config/skills/knowledge/operations/techStack.md +30 -30
  49. package/reference/claude-config/skills/project/SKILL.md +1088 -1088
  50. package/reference/claude-config/skills/run-ui/SKILL.md +73 -73
  51. package/reference/claude-config/skills/save/SKILL.md +3 -3
  52. package/reference/claude-config/skills/setup/SKILL.md +275 -275
  53. package/reference/claude-config/skills/status/SKILL.md +59 -59
  54. package/reference/claude-config/skills/submit-request/SKILL.md +180 -180
  55. package/reference/claude-config/skills/sync/SKILL.md +47 -47
  56. package/reference/claude-config/skills/tutorial/SKILL.md +259 -259
  57. package/reference/claude-config/skills/tutorial/progress-template.md +74 -74
  58. package/reference/claude-config/skills/tutorial/technical.md +1303 -1303
  59. package/reference/claude-config/skills/tutorial/vibe-coder.md +890 -890
  60. package/reference/claude-config/sync-notes/2026-04-22-git-sync-and-sync-notes.md +27 -27
  61. package/reference/claude-config/sync-notes/2026-04-22-lead-gen-deliverability-removal.md +30 -30
  62. package/reference/claude-config/sync-notes/2026-04-24-test-utils-and-template-tests.md +73 -73
  63. package/reference/claude-config/sync-notes/2026-04-24-ui-consolidation-and-sdk-cli-train.md +86 -86
  64. package/reference/claude-config/sync-notes/2026-04-25-auth-role-system-and-settings-roles.md +55 -55
  65. package/reference/claude-config/sync-notes/2026-04-27-crm-hitl-action-layer-cutover.md +97 -97
  66. package/reference/claude-config/sync-notes/2026-04-27-lead-gen-substrate-train.md +112 -112
  67. package/reference/claude-config/sync-notes/2026-04-29-crm-state-and-lead-gen-processing-status.md +93 -93
  68. package/reference/claude-config/sync-notes/2026-05-02-crm-ownership-next-action.md +58 -58
  69. package/reference/claude-config/sync-notes/2026-05-02-template-hardcode-workos-config.md +56 -56
  70. package/reference/claude-config/sync-notes/2026-05-04-elevasis-workspace.md +71 -71
  71. package/reference/claude-config/sync-notes/2026-05-04-knowledge-bundle.md +83 -83
  72. package/reference/claude-config/sync-notes/2026-05-04-template-skills-run-ui-and-tutorial.md +59 -59
  73. package/reference/claude-config/sync-notes/2026-05-05-list-builder.md +42 -42
  74. package/reference/claude-config/sync-notes/2026-05-06-crm-spine.md +60 -60
  75. package/reference/claude-config/sync-notes/2026-05-06-sdk-changes-release-train.md +37 -37
  76. package/reference/claude-config/sync-notes/2026-05-07-sdk-changes-release-train.md +34 -34
  77. package/reference/claude-config/sync-notes/2026-05-08-resource-governance-scaffold-guidance.md +38 -38
  78. package/reference/claude-config/sync-notes/2026-05-09-clients-domain.md +32 -32
  79. package/reference/claude-config/sync-notes/2026-05-09-command-system.md +33 -33
  80. package/reference/claude-config/sync-notes/2026-05-09-resource-governance-and-misc.md +69 -69
  81. package/reference/claude-config/sync-notes/2026-05-12-sdk-ready-release-train.md +30 -30
  82. package/reference/claude-config/sync-notes/2026-05-14-organization-model-ontology-refactor.md +45 -0
  83. package/reference/claude-config/sync-notes/README.md +43 -43
  84. package/reference/cli.mdx +808 -808
  85. package/reference/concepts.mdx +146 -146
  86. package/reference/deployment/api.mdx +297 -297
  87. package/reference/deployment/command-center.mdx +209 -209
  88. package/reference/deployment/index.mdx +195 -195
  89. package/reference/deployment/provided-features.mdx +107 -107
  90. package/reference/deployment/ui-execution.mdx +250 -250
  91. package/reference/examples/organization-model.ts +171 -84
  92. package/reference/framework/agent.mdx +156 -156
  93. package/reference/framework/index.mdx +195 -195
  94. package/reference/framework/interaction-guidance.mdx +182 -182
  95. package/reference/framework/memory.mdx +326 -326
  96. package/reference/framework/project-structure.mdx +282 -282
  97. package/reference/framework/tutorial-system.mdx +135 -135
  98. package/reference/getting-started.mdx +142 -142
  99. package/reference/index.mdx +106 -106
  100. package/reference/packages/core/src/README.md +14 -14
  101. package/reference/packages/core/src/business/README.md +2 -2
  102. package/reference/packages/core/src/knowledge/README.md +32 -32
  103. package/reference/packages/core/src/organization-model/README.md +149 -149
  104. package/reference/packages/core/src/test-utils/README.md +37 -37
  105. package/reference/packages/ui/src/api/README.md +18 -18
  106. package/reference/packages/ui/src/app/README.md +24 -24
  107. package/reference/packages/ui/src/auth/README.md +18 -18
  108. package/reference/packages/ui/src/components/README.md +24 -24
  109. package/reference/packages/ui/src/execution/README.md +16 -16
  110. package/reference/packages/ui/src/features/README.md +28 -28
  111. package/reference/packages/ui/src/graph/README.md +16 -16
  112. package/reference/packages/ui/src/hooks/README.md +23 -23
  113. package/reference/packages/ui/src/initialization/README.md +19 -19
  114. package/reference/packages/ui/src/knowledge/README.md +31 -31
  115. package/reference/packages/ui/src/organization/README.md +18 -18
  116. package/reference/packages/ui/src/profile/README.md +19 -19
  117. package/reference/packages/ui/src/provider/README.md +32 -32
  118. package/reference/packages/ui/src/router/README.md +18 -18
  119. package/reference/packages/ui/src/sse/README.md +13 -13
  120. package/reference/packages/ui/src/test-utils/README.md +7 -7
  121. package/reference/packages/ui/src/theme/README.md +23 -23
  122. package/reference/packages/ui/src/theme/presets/README.md +19 -19
  123. package/reference/packages/ui/src/types/README.md +16 -16
  124. package/reference/packages/ui/src/utils/README.md +18 -18
  125. package/reference/packages/ui/src/zustand/README.md +18 -18
  126. package/reference/platform-tools/adapters-integration.mdx +301 -301
  127. package/reference/platform-tools/adapters-platform.mdx +553 -553
  128. package/reference/platform-tools/index.mdx +217 -217
  129. package/reference/platform-tools/type-safety.mdx +82 -82
  130. package/reference/resources/index.mdx +349 -349
  131. package/reference/resources/patterns.mdx +449 -449
  132. package/reference/resources/types.mdx +116 -116
  133. package/reference/roadmap.mdx +165 -165
  134. package/reference/runtime.mdx +173 -173
  135. package/reference/scaffold/core/organization-graph.mdx +110 -90
  136. package/reference/scaffold/core/organization-model.mdx +225 -213
  137. package/reference/scaffold/index.mdx +67 -67
  138. package/reference/scaffold/operations/propagation-pipeline.md +77 -77
  139. package/reference/scaffold/operations/scaffold-maintenance.md +12 -12
  140. package/reference/scaffold/operations/workflow-recipes.md +138 -138
  141. package/reference/scaffold/recipes/add-a-feature.md +307 -85
  142. package/reference/scaffold/recipes/add-a-resource.md +137 -103
  143. package/reference/scaffold/recipes/customize-knowledge-browser.md +5 -5
  144. package/reference/scaffold/recipes/customize-organization-model.md +275 -138
  145. package/reference/scaffold/recipes/extend-a-base-entity.md +8 -8
  146. package/reference/scaffold/recipes/extend-crm.md +3 -3
  147. package/reference/scaffold/recipes/extend-lead-gen.md +394 -394
  148. package/reference/scaffold/recipes/gate-by-feature-or-admin.md +118 -118
  149. package/reference/scaffold/recipes/index.md +46 -46
  150. package/reference/scaffold/recipes/query-the-knowledge-graph.md +197 -170
  151. package/reference/scaffold/reference/contracts.md +2136 -2093
  152. package/reference/scaffold/reference/glossary.md +76 -76
  153. package/reference/scaffold/ui/composition-extensibility.mdx +233 -233
  154. package/reference/scaffold/ui/customization.md +243 -243
  155. package/reference/scaffold/ui/feature-flags-and-gating.md +46 -46
  156. package/reference/scaffold/ui/feature-shell.mdx +72 -72
  157. package/reference/scaffold/ui/recipes.md +221 -214
  158. package/reference/spine/spine-primer.md +96 -96
  159. package/reference/templates/index.mdx +47 -47
  160. package/reference/troubleshooting.mdx +223 -223
package/dist/index.js CHANGED
@@ -61,73 +61,78 @@ z.object({
61
61
  endDate: z.string().datetime()
62
62
  });
63
63
  var ORGANIZATION_MODEL_ICON_TOKENS = [
64
- "nav.dashboard",
65
- "nav.calendar",
66
- "nav.sales",
67
- "nav.crm",
68
- "nav.lead-gen",
69
- "nav.projects",
70
- "nav.operations",
71
- "nav.monitoring",
72
- "nav.knowledge",
73
- "nav.settings",
74
- "nav.admin",
75
- "nav.archive",
76
- "knowledge.playbook",
77
- "knowledge.strategy",
78
- "knowledge.reference",
79
- "feature.dashboard",
80
- "feature.calendar",
81
- "feature.business",
82
- "feature.sales",
83
- "feature.crm",
84
- "feature.finance",
85
- "feature.lead-gen",
86
- "feature.platform",
87
- "feature.projects",
88
- "feature.operations",
89
- "feature.knowledge",
90
- "feature.monitoring",
91
- "feature.settings",
92
- "feature.admin",
93
- "feature.archive",
94
- "feature.seo",
95
- "resource.agent",
96
- "resource.workflow",
97
- "resource.integration",
98
- "resource.database",
99
- "resource.user",
100
- "resource.team",
101
- "integration.gmail",
102
- "integration.google-sheets",
103
- "integration.attio",
104
- "surface.dashboard",
105
- "surface.calendar",
106
- "surface.overview",
107
- "surface.command-view",
108
- "surface.command-queue",
109
- "surface.pipeline",
110
- "surface.lists",
111
- "surface.resources",
112
- "surface.settings",
113
- "status.success",
114
- "status.error",
115
- "status.warning",
116
- "status.info",
117
- "status.pending",
118
- "action.approve",
119
- "action.reject",
120
- "action.retry",
121
- "action.edit",
122
- "action.view",
123
- "action.launch",
124
- "action.message",
125
- "action.escalate",
126
- "action.promote",
127
- "action.submit",
128
- "action.email"
64
+ // Navigation / app areas
65
+ "dashboard",
66
+ "calendar",
67
+ "sales",
68
+ "crm",
69
+ "lead-gen",
70
+ "projects",
71
+ "operations",
72
+ "monitoring",
73
+ "knowledge",
74
+ "settings",
75
+ "admin",
76
+ "archive",
77
+ "business",
78
+ "finance",
79
+ "platform",
80
+ "seo",
81
+ // Knowledge kinds
82
+ "playbook",
83
+ "strategy",
84
+ "reference",
85
+ // Resource kinds
86
+ "agent",
87
+ "workflow",
88
+ "integration",
89
+ "database",
90
+ "user",
91
+ "team",
92
+ // Integration specifics
93
+ "gmail",
94
+ "google-sheets",
95
+ "attio",
96
+ // Surface / UI views
97
+ "overview",
98
+ "command-view",
99
+ "command-queue",
100
+ "pipeline",
101
+ "lists",
102
+ "resources",
103
+ // Actions
104
+ "approve",
105
+ "reject",
106
+ "retry",
107
+ "edit",
108
+ "view",
109
+ "launch",
110
+ "message",
111
+ "escalate",
112
+ "promote",
113
+ "submit",
114
+ "email",
115
+ // Status
116
+ "success",
117
+ "error",
118
+ "warning",
119
+ "info",
120
+ "pending",
121
+ // OM / UI group icons
122
+ "bolt",
123
+ "building",
124
+ "briefcase",
125
+ "apps",
126
+ "graph",
127
+ "shield",
128
+ "users",
129
+ "chart-bar",
130
+ "search"
129
131
  ];
130
- var CustomIconTokenSchema = z.string().trim().max(80).regex(/^custom\.[a-z0-9]+(?:[-._][a-z0-9]+)*$/, "Custom icon tokens must start with custom.");
132
+ var CustomIconTokenSchema = z.string().trim().max(80).regex(
133
+ /^custom\.[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
134
+ 'Custom icon tokens must start with "custom." followed by lowercase alphanumeric segments'
135
+ );
131
136
  var OrganizationModelBuiltinIconTokenSchema = z.enum(ORGANIZATION_MODEL_ICON_TOKENS);
132
137
  var OrganizationModelIconTokenSchema = z.union([
133
138
  OrganizationModelBuiltinIconTokenSchema,
@@ -140,7 +145,7 @@ var LabelSchema = z.string().trim().min(1).max(120);
140
145
  var DescriptionSchema = z.string().trim().min(1).max(2e3);
141
146
  var ColorTokenSchema = z.string().trim().min(1).max(50);
142
147
  var IconNameSchema = OrganizationModelIconTokenSchema;
143
- z.string().trim().startsWith("/").max(300);
148
+ var PathSchema = z.string().trim().startsWith("/").max(300);
144
149
  var ReferenceIdsSchema = z.array(ModelIdSchema).default([]);
145
150
  var DisplayMetadataSchema = z.object({
146
151
  label: LabelSchema,
@@ -200,7 +205,7 @@ var EntitySchema = z.object({
200
205
  stateCatalogId: ModelIdSchema.optional(),
201
206
  links: z.array(EntityLinkSchema).optional()
202
207
  });
203
- z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
208
+ var EntitiesDomainSchema = z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
204
209
  message: "Each entity entry id must match its map key"
205
210
  }).default({});
206
211
  var ENTITY_ENTRY_INPUTS = [
@@ -298,7 +303,7 @@ var ENTITY_ENTRY_INPUTS = [
298
303
  ]
299
304
  }
300
305
  ];
301
- Object.fromEntries(
306
+ var DEFAULT_ORGANIZATION_MODEL_ENTITIES = Object.fromEntries(
302
307
  ENTITY_ENTRY_INPUTS.map((entity) => {
303
308
  const parsed = EntitySchema.parse(entity);
304
309
  return [parsed.id, parsed];
@@ -315,7 +320,7 @@ var ActionScopeSchema = z.union([
315
320
  domain: ModelIdSchema
316
321
  })
317
322
  ]);
318
- z.object({
323
+ var ActionRefSchema = z.object({
319
324
  actionId: ActionIdSchema.meta({ ref: "action" }),
320
325
  intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
321
326
  });
@@ -359,7 +364,7 @@ var ActionSchema = z.object({
359
364
  knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
360
365
  lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
361
366
  });
362
- z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
367
+ var ActionsDomainSchema = z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
363
368
  message: "Each action entry id must match its map key"
364
369
  }).default({});
365
370
  var LEAD_GEN_ACTION_ENTRY_INPUTS = [
@@ -482,13 +487,2284 @@ var LEAD_GEN_ACTION_ENTRY_INPUTS = [
482
487
  resourceId: "lgn-company-cleanup-workflow",
483
488
  invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/cleanup" }]
484
489
  }
485
- ];
486
- var LEAD_GEN_ACTION_ENTRIES = Object.fromEntries(
487
- LEAD_GEN_ACTION_ENTRY_INPUTS.map((action) => {
488
- const parsed = ActionSchema.parse(action);
489
- return [parsed.id, parsed];
490
- })
491
- );
490
+ ];
491
+ var LEAD_GEN_ACTION_ENTRIES = Object.fromEntries(
492
+ LEAD_GEN_ACTION_ENTRY_INPUTS.map((action) => {
493
+ const parsed = ActionSchema.parse(action);
494
+ return [parsed.id, parsed];
495
+ })
496
+ );
497
+ var CRM_ACTION_ENTRY_INPUTS = [
498
+ {
499
+ id: "send_reply",
500
+ order: 210,
501
+ label: "Send Reply",
502
+ description: "Send a contextual reply for an active CRM deal.",
503
+ scope: { domain: "sales" },
504
+ resourceId: "crm-send-reply-workflow",
505
+ affects: ["crm.deal"]
506
+ },
507
+ {
508
+ id: "send_link",
509
+ order: 220,
510
+ label: "Send Booking Link",
511
+ description: "Send a booking link to move a deal toward a scheduled call.",
512
+ scope: { domain: "sales" },
513
+ resourceId: "crm-send-booking-link-workflow",
514
+ affects: ["crm.deal"]
515
+ },
516
+ {
517
+ id: "send_nudge",
518
+ order: 230,
519
+ label: "Send Nudge",
520
+ description: "Send a follow-up nudge for a stalled CRM deal.",
521
+ scope: { domain: "sales" },
522
+ resourceId: "crm-send-nudge-workflow",
523
+ affects: ["crm.deal"]
524
+ },
525
+ {
526
+ id: "rebook",
527
+ order: 240,
528
+ label: "Rebook",
529
+ description: "Rebook a missed or rescheduled CRM appointment.",
530
+ scope: { domain: "sales" },
531
+ resourceId: "crm-rebook-workflow",
532
+ affects: ["crm.deal"]
533
+ },
534
+ {
535
+ id: "move_to_proposal",
536
+ order: 250,
537
+ label: "Move to Proposal",
538
+ description: "Advance a qualified CRM deal into the proposal stage.",
539
+ scope: { domain: "sales" },
540
+ resourceId: "move_to_proposal-workflow",
541
+ affects: ["crm.deal"]
542
+ },
543
+ {
544
+ id: "move_to_closing",
545
+ order: 260,
546
+ label: "Move to Closing",
547
+ description: "Advance a proposal-stage CRM deal into closing.",
548
+ scope: { domain: "sales" },
549
+ resourceId: "move_to_closing-workflow",
550
+ affects: ["crm.deal"]
551
+ },
552
+ {
553
+ id: "move_to_closed_won",
554
+ order: 270,
555
+ label: "Close Won",
556
+ description: "Mark a CRM deal as closed won.",
557
+ scope: { domain: "sales" },
558
+ resourceId: "move_to_closed_won-workflow",
559
+ affects: ["crm.deal"]
560
+ },
561
+ {
562
+ id: "move_to_closed_lost",
563
+ order: 280,
564
+ label: "Close Lost",
565
+ description: "Mark a CRM deal as closed lost.",
566
+ scope: { domain: "sales" },
567
+ resourceId: "move_to_closed_lost-workflow",
568
+ affects: ["crm.deal"]
569
+ },
570
+ {
571
+ id: "move_to_nurturing",
572
+ order: 290,
573
+ label: "Move to Nurturing",
574
+ description: "Move a CRM deal into nurturing for future follow-up.",
575
+ scope: { domain: "sales" },
576
+ resourceId: "move_to_nurturing-workflow",
577
+ affects: ["crm.deal"]
578
+ }
579
+ ];
580
+ var CRM_ACTION_ENTRIES = Object.fromEntries(
581
+ CRM_ACTION_ENTRY_INPUTS.map((action) => {
582
+ const parsed = ActionSchema.parse(action);
583
+ return [parsed.id, parsed];
584
+ })
585
+ );
586
+ var DEFAULT_ORGANIZATION_MODEL_ACTIONS = {
587
+ ...LEAD_GEN_ACTION_ENTRIES,
588
+ ...CRM_ACTION_ENTRIES
589
+ };
590
+ var ContentNodeBaseSchema = z.object({
591
+ /** Human-readable label for the content node. */
592
+ label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
593
+ /** Optional one-paragraph description. */
594
+ description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
595
+ /** Optional display order within the system content map. */
596
+ order: z.number().int().optional().meta({ label: "Order" }),
597
+ /**
598
+ * Local NodeId of the parent content node within the SAME system.
599
+ * Per B4/L9: MUST resolve to a sibling in the same `system.content` map.
600
+ * Per L19: parent and child MUST share the same `kind` (meta-category).
601
+ */
602
+ parentContentId: z.string().trim().min(1).max(200).optional().meta({ label: "Parent content id" })
603
+ });
604
+ var ContentNodeSchema = ContentNodeBaseSchema.extend({
605
+ /** Meta-category (e.g. 'schema', 'config', 'knowledge', tenant-defined). */
606
+ kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
607
+ /** Specific family within the meta-category (e.g. 'pipeline', 'kv'). */
608
+ type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
609
+ /** Payload data; validated against registered payloadSchema when (kind, type) is known. */
610
+ data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
611
+ });
612
+ z.object({
613
+ /** Meta-category (tenant-defined or registry-shipped). */
614
+ kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
615
+ /** Specific family within the meta-category. */
616
+ type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
617
+ /** Human-readable label shown in the KB tree and describe views. */
618
+ label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
619
+ /** Optional description. */
620
+ description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
621
+ /**
622
+ * Which KB tree group this extension renders in.
623
+ * Per L6: 'business-model' places it alongside Customers / Offerings / Goals.
624
+ */
625
+ treeGroup: z.union([z.enum(["profile", "business-model", "systems", "graph", "governance-wiring"]), z.string().min(1).max(100)]).meta({ label: "Tree group" }),
626
+ /** Untyped payload; shape governed by the registered payloadSchema when available. */
627
+ data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
628
+ });
629
+ var OntologyKindSchema = z.enum([
630
+ "object",
631
+ "link",
632
+ "action",
633
+ "catalog",
634
+ "event",
635
+ "interface",
636
+ "value-type",
637
+ "property",
638
+ "group",
639
+ "surface"
640
+ ]);
641
+ var SYSTEM_PATH_PATTERN = "[a-z0-9][a-z0-9-]*(?:\\.[a-z0-9][a-z0-9-]*)*";
642
+ var LOCAL_ID_PATTERN = "[a-z0-9][a-z0-9._-]*";
643
+ var ONTOLOGY_ID_PATTERN = `^(global|${SYSTEM_PATH_PATTERN}):(${OntologyKindSchema.options.join("|")})\\/(${LOCAL_ID_PATTERN})$`;
644
+ var ONTOLOGY_ID_REGEX = new RegExp(ONTOLOGY_ID_PATTERN);
645
+ var OntologyIdSchema = z.string().trim().min(1).max(300).regex(
646
+ ONTOLOGY_ID_REGEX,
647
+ "Ontology IDs must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
648
+ );
649
+ function parseOntologyId(id) {
650
+ const normalized = OntologyIdSchema.parse(id);
651
+ const match = ONTOLOGY_ID_REGEX.exec(normalized);
652
+ if (match === null) {
653
+ throw new Error(`Invalid ontology ID "${id}"`);
654
+ }
655
+ return {
656
+ id: normalized,
657
+ scope: match[1],
658
+ kind: match[2],
659
+ localId: match[3],
660
+ isGlobal: match[1] === "global"
661
+ };
662
+ }
663
+ function formatOntologyId(input) {
664
+ return OntologyIdSchema.parse(`${input.scope}:${input.kind}/${input.localId}`);
665
+ }
666
+ var OntologyReferenceListSchema = z.array(OntologyIdSchema).default([]).optional();
667
+ var OntologyRecordBaseSchema = z.object({
668
+ id: OntologyIdSchema,
669
+ label: z.string().trim().min(1).max(160).optional(),
670
+ description: z.string().trim().min(1).max(2e3).optional(),
671
+ ownerSystemId: z.string().trim().min(1).max(200).optional(),
672
+ aliases: z.array(OntologyIdSchema).optional()
673
+ }).passthrough();
674
+ var OntologyObjectTypeSchema = OntologyRecordBaseSchema.extend({
675
+ properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
676
+ storage: z.record(z.string(), z.unknown()).optional()
677
+ });
678
+ var OntologyLinkTypeSchema = OntologyRecordBaseSchema.extend({
679
+ from: OntologyIdSchema,
680
+ to: OntologyIdSchema,
681
+ cardinality: z.string().trim().min(1).max(80).optional(),
682
+ via: z.string().trim().min(1).max(255).optional()
683
+ });
684
+ var OntologyActionTypeSchema = OntologyRecordBaseSchema.extend({
685
+ actsOn: OntologyReferenceListSchema,
686
+ input: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
687
+ effects: z.array(z.record(z.string(), z.unknown())).optional()
688
+ });
689
+ var OntologyCatalogTypeSchema = OntologyRecordBaseSchema.extend({
690
+ kind: z.string().trim().min(1).max(120).optional(),
691
+ appliesTo: OntologyIdSchema.optional(),
692
+ entries: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
693
+ });
694
+ var OntologyEventTypeSchema = OntologyRecordBaseSchema.extend({
695
+ payload: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
696
+ });
697
+ var OntologyInterfaceTypeSchema = OntologyRecordBaseSchema.extend({
698
+ properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
699
+ });
700
+ var OntologyValueTypeSchema = OntologyRecordBaseSchema.extend({
701
+ primitive: z.string().trim().min(1).max(120).optional()
702
+ });
703
+ var OntologySharedPropertySchema = OntologyRecordBaseSchema.extend({
704
+ valueType: OntologyIdSchema.optional(),
705
+ searchable: z.boolean().optional(),
706
+ pii: z.boolean().optional()
707
+ });
708
+ var OntologyGroupSchema = OntologyRecordBaseSchema.extend({
709
+ members: OntologyReferenceListSchema
710
+ });
711
+ var OntologySurfaceTypeSchema = OntologyRecordBaseSchema.extend({
712
+ route: z.string().trim().min(1).max(500).optional()
713
+ });
714
+ var OntologyScopeSchema = z.object({
715
+ objectTypes: z.record(OntologyIdSchema, OntologyObjectTypeSchema).default({}).optional(),
716
+ linkTypes: z.record(OntologyIdSchema, OntologyLinkTypeSchema).default({}).optional(),
717
+ actionTypes: z.record(OntologyIdSchema, OntologyActionTypeSchema).default({}).optional(),
718
+ catalogTypes: z.record(OntologyIdSchema, OntologyCatalogTypeSchema).default({}).optional(),
719
+ eventTypes: z.record(OntologyIdSchema, OntologyEventTypeSchema).default({}).optional(),
720
+ interfaceTypes: z.record(OntologyIdSchema, OntologyInterfaceTypeSchema).default({}).optional(),
721
+ valueTypes: z.record(OntologyIdSchema, OntologyValueTypeSchema).default({}).optional(),
722
+ sharedProperties: z.record(OntologyIdSchema, OntologySharedPropertySchema).default({}).optional(),
723
+ groups: z.record(OntologyIdSchema, OntologyGroupSchema).default({}).optional(),
724
+ surfaces: z.record(OntologyIdSchema, OntologySurfaceTypeSchema).default({}).optional()
725
+ }).default({});
726
+ var DEFAULT_ONTOLOGY_SCOPE = {
727
+ valueTypes: {
728
+ "global:value-type/uuid": {
729
+ id: "global:value-type/uuid",
730
+ label: "UUID",
731
+ primitive: "string"
732
+ },
733
+ "global:value-type/text": {
734
+ id: "global:value-type/text",
735
+ label: "Text",
736
+ primitive: "string"
737
+ },
738
+ "global:value-type/url": {
739
+ id: "global:value-type/url",
740
+ label: "URL",
741
+ primitive: "string"
742
+ },
743
+ "global:value-type/email": {
744
+ id: "global:value-type/email",
745
+ label: "Email",
746
+ primitive: "string"
747
+ }
748
+ }
749
+ };
750
+ var SCOPE_KIND = {
751
+ objectTypes: "object",
752
+ linkTypes: "link",
753
+ actionTypes: "action",
754
+ catalogTypes: "catalog",
755
+ eventTypes: "event",
756
+ interfaceTypes: "interface",
757
+ valueTypes: "value-type",
758
+ sharedProperties: "property",
759
+ groups: "group",
760
+ surfaces: "surface"
761
+ };
762
+ var SCOPE_KEYS = Object.keys(SCOPE_KIND);
763
+ function listResolvedOntologyRecords(index) {
764
+ return SCOPE_KEYS.flatMap((scopeKey) => {
765
+ const kind = SCOPE_KIND[scopeKey];
766
+ return Object.entries(index[scopeKey]).sort(([leftId], [rightId]) => leftId.localeCompare(rightId)).map(([id, record]) => ({
767
+ id,
768
+ kind,
769
+ record
770
+ }));
771
+ });
772
+ }
773
+ function originFromContext(context) {
774
+ return {
775
+ kind: context.kind,
776
+ source: context.source,
777
+ path: context.path,
778
+ ...context.systemPath !== void 0 ? { systemPath: context.systemPath } : {},
779
+ ...context.legacyId !== void 0 ? { legacyId: context.legacyId } : {}
780
+ };
781
+ }
782
+ function createEmptyIndex() {
783
+ return {
784
+ objectTypes: {},
785
+ linkTypes: {},
786
+ actionTypes: {},
787
+ catalogTypes: {},
788
+ eventTypes: {},
789
+ interfaceTypes: {},
790
+ valueTypes: {},
791
+ sharedProperties: {},
792
+ groups: {},
793
+ surfaces: {}
794
+ };
795
+ }
796
+ function sortResolvedOntologyIndex(index) {
797
+ const sorted = createEmptyIndex();
798
+ for (const scopeKey of SCOPE_KEYS) {
799
+ const target = sorted[scopeKey];
800
+ for (const [id, record] of Object.entries(index[scopeKey]).sort(
801
+ ([leftId], [rightId]) => leftId.localeCompare(rightId)
802
+ )) {
803
+ target[id] = record;
804
+ }
805
+ }
806
+ return sorted;
807
+ }
808
+ function childSystemsOf(system) {
809
+ return system.systems ?? system.subsystems ?? {};
810
+ }
811
+ function addRecord(index, diagnostics, sourcesById, scopeKey, record, context) {
812
+ let parsed;
813
+ try {
814
+ parsed = parseOntologyId(record.id);
815
+ } catch {
816
+ diagnostics.push({
817
+ code: "invalid_ontology_id",
818
+ message: `Invalid ontology ID "${record.id}" from ${context.source} at ${context.path.join(".")}`,
819
+ id: record.id,
820
+ path: context.path,
821
+ source: context.source,
822
+ origin: originFromContext(context)
823
+ });
824
+ return;
825
+ }
826
+ const expectedKind = SCOPE_KIND[scopeKey];
827
+ if (parsed.kind !== expectedKind) {
828
+ diagnostics.push({
829
+ code: "ontology_kind_mismatch",
830
+ message: `Ontology ID "${record.id}" has kind "${parsed.kind}" but was authored in ${scopeKey} (${expectedKind}) at ${context.path.join(".")}`,
831
+ id: record.id,
832
+ path: context.path,
833
+ source: context.source,
834
+ origin: originFromContext(context)
835
+ });
836
+ return;
837
+ }
838
+ const existing = sourcesById.get(parsed.id);
839
+ if (existing !== void 0) {
840
+ diagnostics.push({
841
+ code: "duplicate_ontology_id",
842
+ message: `Duplicate ontology ID "${parsed.id}" from ${context.source} at ${context.path.join(".")} conflicts with ${existing.source} at ${existing.path.join(".")}`,
843
+ id: parsed.id,
844
+ path: context.path,
845
+ source: context.source,
846
+ origin: originFromContext(context),
847
+ existingSource: existing.source,
848
+ existingOrigin: originFromContext(existing)
849
+ });
850
+ return;
851
+ }
852
+ sourcesById.set(parsed.id, context);
853
+ index[scopeKey][parsed.id] = {
854
+ ...record,
855
+ origin: originFromContext(context)
856
+ };
857
+ }
858
+ function addScope(index, diagnostics, sourcesById, scope, source, path) {
859
+ if (scope === void 0) return;
860
+ for (const scopeKey of SCOPE_KEYS) {
861
+ const records = scope[scopeKey] ?? {};
862
+ for (const [key, record] of Object.entries(records)) {
863
+ addRecord(index, diagnostics, sourcesById, scopeKey, record, {
864
+ source,
865
+ path: [...path, scopeKey, key],
866
+ kind: "authored",
867
+ systemPath: source.startsWith("system:") ? source.slice("system:".length, -".ontology".length) : void 0
868
+ });
869
+ }
870
+ }
871
+ }
872
+ function legacyObjectId(entity) {
873
+ return formatOntologyId({ scope: entity.ownedBySystemId, kind: "object", localId: entity.id });
874
+ }
875
+ function legacyActionOwner(action, entities) {
876
+ const firstAffectedEntityId = action.affects?.find((entityId) => entities[entityId] !== void 0);
877
+ if (firstAffectedEntityId !== void 0) {
878
+ return entities[firstAffectedEntityId].ownedBySystemId;
879
+ }
880
+ if (typeof action.scope === "object") {
881
+ return action.scope.domain;
882
+ }
883
+ return "global";
884
+ }
885
+ function addLegacyEntityProjections(index, diagnostics, sourcesById, entities) {
886
+ for (const entity of Object.values(entities)) {
887
+ const objectType = {
888
+ id: legacyObjectId(entity),
889
+ label: entity.label,
890
+ description: entity.description,
891
+ ownerSystemId: entity.ownedBySystemId,
892
+ ...entity.table !== void 0 ? {
893
+ storage: {
894
+ kind: "table",
895
+ table: entity.table
896
+ }
897
+ } : {},
898
+ ...entity.rowSchema !== void 0 ? { rowSchema: entity.rowSchema } : {},
899
+ ...entity.stateCatalogId !== void 0 ? { stateCatalogId: entity.stateCatalogId } : {}
900
+ };
901
+ addRecord(index, diagnostics, sourcesById, "objectTypes", objectType, {
902
+ source: "legacy.entities",
903
+ path: ["entities", entity.id],
904
+ kind: "projected",
905
+ systemPath: entity.ownedBySystemId,
906
+ legacyId: entity.id
907
+ });
908
+ entity.links?.forEach((link, linkIndex) => {
909
+ const targetEntity = entities[link.toEntity];
910
+ if (targetEntity === void 0) return;
911
+ const linkType = {
912
+ id: formatOntologyId({
913
+ scope: entity.ownedBySystemId,
914
+ kind: "link",
915
+ localId: `${entity.id}-${link.toEntity}-${linkIndex}`
916
+ }),
917
+ label: link.label ?? link.kind,
918
+ ownerSystemId: entity.ownedBySystemId,
919
+ from: legacyObjectId(entity),
920
+ to: legacyObjectId(targetEntity),
921
+ cardinality: link.kind,
922
+ ...link.via !== void 0 ? { via: link.via } : {}
923
+ };
924
+ addRecord(index, diagnostics, sourcesById, "linkTypes", linkType, {
925
+ source: "legacy.entities.links",
926
+ path: ["entities", entity.id, "links", linkIndex],
927
+ kind: "projected",
928
+ systemPath: entity.ownedBySystemId,
929
+ legacyId: `${entity.id}.links.${linkIndex}`
930
+ });
931
+ });
932
+ }
933
+ }
934
+ function addLegacyActionProjections(index, diagnostics, sourcesById, actions, entities) {
935
+ for (const action of Object.values(actions)) {
936
+ const ownerSystemId = legacyActionOwner(action, entities);
937
+ const actionType = {
938
+ id: formatOntologyId({ scope: ownerSystemId, kind: "action", localId: action.id }),
939
+ label: action.label,
940
+ description: action.description,
941
+ ownerSystemId,
942
+ actsOn: action.affects?.map((entityId) => entities[entityId] ? legacyObjectId(entities[entityId]) : void 0).filter((id) => id !== void 0),
943
+ ...action.resourceId !== void 0 ? { resourceId: action.resourceId } : {},
944
+ ...action.invocations !== void 0 ? { invocations: action.invocations } : {},
945
+ ...action.lifecycle !== void 0 ? { lifecycle: action.lifecycle } : {},
946
+ legacyActionId: action.id
947
+ };
948
+ addRecord(index, diagnostics, sourcesById, "actionTypes", actionType, {
949
+ source: "legacy.actions",
950
+ path: ["actions", action.id],
951
+ kind: "projected",
952
+ systemPath: ownerSystemId,
953
+ legacyId: action.id
954
+ });
955
+ }
956
+ }
957
+ function addSystemContentProjections(index, diagnostics, sourcesById, systemPath, system, schemaPath) {
958
+ const content = system.content ?? {};
959
+ for (const [localId, node] of Object.entries(content)) {
960
+ if (node.kind !== "schema") continue;
961
+ const entries = Object.fromEntries(
962
+ Object.entries(content).filter(([, candidate]) => candidate.parentContentId === localId).map(([entryId, candidate]) => [
963
+ entryId,
964
+ {
965
+ label: candidate.label ?? entryId,
966
+ type: candidate.type,
967
+ ...candidate.description !== void 0 ? { description: candidate.description } : {},
968
+ ...candidate.data !== void 0 ? candidate.data : {}
969
+ }
970
+ ])
971
+ );
972
+ const catalogType = {
973
+ id: formatOntologyId({ scope: systemPath, kind: "catalog", localId }),
974
+ label: node.label ?? localId,
975
+ description: node.description,
976
+ ownerSystemId: systemPath,
977
+ kind: node.type,
978
+ ...typeof node.data?.["entityId"] === "string" ? { appliesTo: formatOntologyId({ scope: systemPath, kind: "object", localId: node.data["entityId"] }) } : {},
979
+ ...Object.keys(entries).length > 0 ? { entries } : {},
980
+ ...node.data !== void 0 ? { data: node.data } : {}
981
+ };
982
+ addRecord(index, diagnostics, sourcesById, "catalogTypes", catalogType, {
983
+ source: "legacy.system.content",
984
+ path: [...schemaPath, "content", localId],
985
+ kind: "projected",
986
+ systemPath,
987
+ legacyId: `${systemPath}:${localId}`
988
+ });
989
+ }
990
+ }
991
+ function addSystemScopes(index, diagnostics, sourcesById, systems, prefix, schemaPath) {
992
+ for (const [key, system] of Object.entries(systems)) {
993
+ const systemPath = prefix ? `${prefix}.${key}` : key;
994
+ const currentPath = [...schemaPath, key];
995
+ addScope(index, diagnostics, sourcesById, system.ontology, `system:${systemPath}.ontology`, [
996
+ ...currentPath,
997
+ "ontology"
998
+ ]);
999
+ addSystemContentProjections(index, diagnostics, sourcesById, systemPath, system, currentPath);
1000
+ addSystemScopes(index, diagnostics, sourcesById, childSystemsOf(system), systemPath, [
1001
+ ...currentPath,
1002
+ system.systems !== void 0 ? "systems" : "subsystems"
1003
+ ]);
1004
+ }
1005
+ }
1006
+ function compileOrganizationOntology(model) {
1007
+ const ontology = createEmptyIndex();
1008
+ const diagnostics = [];
1009
+ const sourcesById = /* @__PURE__ */ new Map();
1010
+ addScope(ontology, diagnostics, sourcesById, model.ontology, "organization.ontology", ["ontology"]);
1011
+ addSystemScopes(ontology, diagnostics, sourcesById, model.systems ?? {}, "", ["systems"]);
1012
+ addLegacyEntityProjections(ontology, diagnostics, sourcesById, model.entities ?? {});
1013
+ addLegacyActionProjections(ontology, diagnostics, sourcesById, model.actions ?? {}, model.entities ?? {});
1014
+ return { ontology: sortResolvedOntologyIndex(ontology), diagnostics };
1015
+ }
1016
+
1017
+ // ../core/src/organization-model/domains/systems.ts
1018
+ var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
1019
+ var SystemLifecycleSchema = z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
1020
+ var SystemStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Status", color: "teal" });
1021
+ var SystemIdSchema = ModelIdSchema;
1022
+ var SystemPathSchema = z.string().trim().min(1).regex(
1023
+ /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
1024
+ 'must be a dotted lowercase path (e.g. "sales.lead-gen" or "sales.crm")'
1025
+ );
1026
+ var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]).meta({ label: "UI position" });
1027
+ var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(
1028
+ /^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
1029
+ "Node references must use kind:dotted-path (e.g. system:sales.crm or content-node:sales.crm:pipeline-id)"
1030
+ );
1031
+ var SystemUiSchema = z.object({
1032
+ path: PathSchema,
1033
+ surfaces: ReferenceIdsSchema,
1034
+ icon: IconNameSchema.optional(),
1035
+ order: z.number().int().optional()
1036
+ });
1037
+ var JsonValueSchema = z.lazy(
1038
+ () => z.union([
1039
+ z.string(),
1040
+ z.number(),
1041
+ z.boolean(),
1042
+ z.null(),
1043
+ z.array(JsonValueSchema),
1044
+ z.record(z.string(), JsonValueSchema)
1045
+ ])
1046
+ );
1047
+ var SystemConfigSchema = z.record(z.string().trim().min(1).max(200), JsonValueSchema).default({}).optional();
1048
+ var SystemEntrySchema = z.object({
1049
+ /** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
1050
+ id: SystemIdSchema,
1051
+ /** Human-readable system label shown in UI, governance, and operations surfaces. */
1052
+ label: LabelSchema.optional(),
1053
+ /** @deprecated Use label. Accepted for pre-consolidation System declarations. */
1054
+ title: LabelSchema.optional(),
1055
+ /** One-paragraph purpose statement for the bounded context. */
1056
+ description: DescriptionSchema.optional(),
1057
+ /** Closed system shape enum; catalog values remain tenant-defined. */
1058
+ kind: SystemKindSchema.optional(),
1059
+ /** Optional self-reference for System hierarchy. */
1060
+ parentSystemId: SystemIdSchema.optional(),
1061
+ /** Optional UI presence. Systems without UI omit this. */
1062
+ ui: SystemUiSchema.optional(),
1063
+ /** Canonical lifecycle state. Replaces Feature.enabled/devOnly and System.status. */
1064
+ lifecycle: SystemLifecycleSchema.optional(),
1065
+ /** Optional role responsible for this system. */
1066
+ responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
1067
+ /** Optional knowledge nodes that govern this system. */
1068
+ governedByKnowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
1069
+ /** Optional actions this system exposes or consumes. */
1070
+ actions: z.array(ActionRefSchema).optional(),
1071
+ /** Optional operational policies that apply to this system. */
1072
+ policies: z.array(ModelIdSchema.meta({ ref: "policy" })).default([]).optional(),
1073
+ /** Optional goals this system contributes to. */
1074
+ drivesGoals: z.array(ModelIdSchema.meta({ ref: "goal" })).default([]).optional(),
1075
+ /** @deprecated Use lifecycle. Accepted for one publish cycle. */
1076
+ status: SystemStatusSchema.optional(),
1077
+ /** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
1078
+ path: PathSchema.optional(),
1079
+ /** @deprecated Use ui.icon. Kept for one-cycle Feature compatibility. */
1080
+ icon: IconNameSchema.optional(),
1081
+ /** @deprecated Feature color token, retained for one-cycle compatibility. */
1082
+ color: ColorTokenSchema.optional(),
1083
+ /** @deprecated UI placement hint, retained for one-cycle compatibility. */
1084
+ uiPosition: UiPositionSchema.optional(),
1085
+ /** @deprecated Use lifecycle. */
1086
+ enabled: z.boolean().optional(),
1087
+ /** @deprecated Use lifecycle: "beta". */
1088
+ devOnly: z.boolean().optional(),
1089
+ requiresAdmin: z.boolean().optional(),
1090
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1091
+ order: z.number(),
1092
+ /**
1093
+ * System-local JSON settings and defaults. Strongly typed OM fields,
1094
+ * secrets, credentials, and runtime state stay outside this bucket.
1095
+ */
1096
+ config: SystemConfigSchema,
1097
+ /**
1098
+ * System-owned ontology declarations. `systems` is now the canonical child
1099
+ * key; this scope holds the object, action, catalog, link, event, and
1100
+ * shared contract records owned by this system.
1101
+ */
1102
+ ontology: OntologyScopeSchema.optional(),
1103
+ /**
1104
+ * @deprecated Compatibility-only bridge for old tenant content nodes and
1105
+ * migration readers. New schema/catalog authoring belongs in ontology;
1106
+ * new system-local settings belong in config. Bridge nodes are keyed by
1107
+ * local NodeId and may still project to content-node:* graph IDs.
1108
+ */
1109
+ content: z.record(z.string().trim().min(1).max(200), ContentNodeSchema).optional(),
1110
+ /**
1111
+ * Recursive child systems, authored via nesting (per L11).
1112
+ * The key is the local system id; the full path is computed by joining
1113
+ * ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
1114
+ * Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
1115
+ * position-derived paths. Both still exist on this schema for backward compat.
1116
+ */
1117
+ systems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional(),
1118
+ /** @deprecated Use systems. Accepted as a compatibility alias during the ontology bridge. */
1119
+ subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
1120
+ }).refine((system) => system.label !== void 0 || system.title !== void 0, {
1121
+ path: ["label"],
1122
+ message: "System must provide label or title"
1123
+ }).transform((system) => {
1124
+ const normalizedSystem = system.systems !== void 0 && system.subsystems === void 0 ? { ...system, subsystems: system.systems } : system;
1125
+ if (normalizedSystem.status === void 0) return normalizedSystem;
1126
+ console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
1127
+ return normalizedSystem.lifecycle === void 0 ? { ...normalizedSystem, lifecycle: normalizedSystem.status } : normalizedSystem;
1128
+ });
1129
+ var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1130
+ message: "Each system entry id must match its map key"
1131
+ }).default({});
1132
+ var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {};
1133
+
1134
+ // ../core/src/organization-model/content-kinds/registry.ts
1135
+ function defineContentType(def) {
1136
+ return def;
1137
+ }
1138
+ var PipelinePayloadSchema = z.object({
1139
+ /**
1140
+ * Local NodeId of the entity this pipeline applies to (e.g. 'crm.deal').
1141
+ * `.meta({ ref: 'entity' })` enables SchemaDrivenFieldList to render a
1142
+ * clickable graph link to the referenced entity node.
1143
+ */
1144
+ entityId: z.string().trim().min(1).max(200).meta({ label: "Entity", ref: "entity", hint: "The entity type this pipeline tracks" }),
1145
+ /**
1146
+ * Optional Kanban column color token for UI rendering.
1147
+ */
1148
+ kanbanColor: z.string().trim().min(1).max(40).optional().meta({ label: "Kanban color", hint: "UI color token" })
1149
+ });
1150
+ var pipelineKind = defineContentType({
1151
+ kind: "schema",
1152
+ type: "pipeline",
1153
+ label: "Pipeline",
1154
+ description: "A named progression pipeline that applies to a specific entity type.",
1155
+ payloadSchema: PipelinePayloadSchema,
1156
+ parentTypes: []
1157
+ });
1158
+ var StagePayloadSchema = z.object({
1159
+ /**
1160
+ * Semantic classification for this stage.
1161
+ * Drives color, icon, and CRM-priority logic in consuming views.
1162
+ * Optional — prospecting stages use data.entityKind instead.
1163
+ * Enum aligned with SalesStageSemanticClassSchema (sales.ts).
1164
+ */
1165
+ semanticClass: z.enum(["open", "active", "nurturing", "closed_won", "closed_lost", "won", "lost", "closed"]).optional().meta({ label: "Semantic class", hint: "Semantic meaning of this stage", color: "blue" })
1166
+ });
1167
+ var stageKind = defineContentType({
1168
+ kind: "schema",
1169
+ type: "stage",
1170
+ label: "Stage",
1171
+ description: "A stage within a pipeline. Must be parented under a schema:pipeline content node.",
1172
+ payloadSchema: StagePayloadSchema,
1173
+ parentTypes: ["schema:pipeline"]
1174
+ });
1175
+ var TemplatePayloadSchema = z.object({
1176
+ /**
1177
+ * Optional description surfaced in the KB describe view and tooling.
1178
+ */
1179
+ description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description", hint: "What this template is used for" })
1180
+ });
1181
+ var templateKind = defineContentType({
1182
+ kind: "schema",
1183
+ type: "template",
1184
+ label: "Template",
1185
+ description: "A named build template (e.g. a prospecting pipeline sequence).",
1186
+ payloadSchema: TemplatePayloadSchema,
1187
+ parentTypes: []
1188
+ });
1189
+ var TemplateStepPayloadSchema = z.object({
1190
+ /**
1191
+ * Which entity type this step primarily operates on.
1192
+ */
1193
+ primaryEntity: z.enum(["company", "contact"]).meta({ label: "Primary entity", hint: "Entity type this step processes", color: "blue" }),
1194
+ /**
1195
+ * Action key identifying the workflow action executed by this step.
1196
+ * `.meta({ ref: 'action' })` enables SchemaDrivenFieldList to render a
1197
+ * clickable graph link.
1198
+ */
1199
+ actionKey: z.string().trim().min(1).max(200).meta({ label: "Action", ref: "action", hint: "Workflow action executed by this step" }),
1200
+ /**
1201
+ * IDs of sibling step local NodeIds this step depends on.
1202
+ */
1203
+ dependsOn: z.array(z.string().trim().min(1).max(200)).optional().meta({ label: "Depends on", hint: "Local NodeIds of prerequisite steps" })
1204
+ });
1205
+ var templateStepKind = defineContentType({
1206
+ kind: "schema",
1207
+ type: "template-step",
1208
+ label: "Template Step",
1209
+ description: "A step within a build template. Must be parented under a schema:template content node.",
1210
+ payloadSchema: TemplateStepPayloadSchema,
1211
+ parentTypes: ["schema:template"]
1212
+ });
1213
+ var StatusFlowPayloadSchema = z.object({
1214
+ /**
1215
+ * Which entity scope this status flow governs.
1216
+ */
1217
+ appliesTo: z.enum(["project", "milestone", "task"]).meta({ label: "Applies to", hint: "Entity scope governed by this status flow", color: "blue" })
1218
+ });
1219
+ var statusFlowKind = defineContentType({
1220
+ kind: "schema",
1221
+ type: "status-flow",
1222
+ label: "Status Flow",
1223
+ description: "A named set of statuses governing a project, milestone, or task entity.",
1224
+ payloadSchema: StatusFlowPayloadSchema,
1225
+ parentTypes: []
1226
+ });
1227
+ var StatusPayloadSchema = z.object({
1228
+ /**
1229
+ * Semantic classification string for this status.
1230
+ * Free-form to allow tenant-defined classifications (e.g. 'active', 'blocked',
1231
+ * 'completed'). Used by UI to apply color and icon fallbacks.
1232
+ * Optional — status nodes may omit this when the label is self-descriptive.
1233
+ */
1234
+ semanticClass: z.string().trim().min(1).max(100).optional().meta({ label: "Semantic class", hint: "Semantic meaning of this status (e.g. active, blocked, completed)" }),
1235
+ /**
1236
+ * Optional UI color token override for this status.
1237
+ */
1238
+ color: z.string().trim().min(1).max(40).optional().meta({ label: "Color", hint: "UI color token" })
1239
+ });
1240
+ var statusKind = defineContentType({
1241
+ kind: "schema",
1242
+ type: "status",
1243
+ label: "Status",
1244
+ description: "A single status within a status flow. Must be parented under a schema:status-flow content node.",
1245
+ payloadSchema: StatusPayloadSchema,
1246
+ parentTypes: ["schema:status-flow"]
1247
+ });
1248
+ var ConfigKvPayloadSchema = z.object({
1249
+ /**
1250
+ * Flat key-value entries. Values are JSON primitives.
1251
+ * Keys are short identifiers (e.g. 'maxBatchSize', 'featureEnabled').
1252
+ */
1253
+ entries: z.record(z.string().trim().min(1).max(200), z.union([z.string(), z.number(), z.boolean(), z.null()])).meta({ label: "Entries", hint: "Key-value configuration entries (string, number, boolean, or null values)" })
1254
+ });
1255
+ var configKvKind = defineContentType({
1256
+ kind: "config",
1257
+ type: "kv",
1258
+ label: "Key-Value Config",
1259
+ description: "A flat key-value configuration store co-located with a system. Values are JSON primitives.",
1260
+ payloadSchema: ConfigKvPayloadSchema,
1261
+ parentTypes: []
1262
+ });
1263
+
1264
+ // ../core/src/organization-model/content-kinds/index.ts
1265
+ var CONTENT_KIND_REGISTRY = {
1266
+ "schema:pipeline": pipelineKind,
1267
+ "schema:stage": stageKind,
1268
+ "schema:template": templateKind,
1269
+ "schema:template-step": templateStepKind,
1270
+ "schema:status-flow": statusFlowKind,
1271
+ "schema:status": statusKind,
1272
+ "config:kv": configKvKind
1273
+ };
1274
+ function lookupContentType(kind, type) {
1275
+ const key = `${kind}:${type}`;
1276
+ return CONTENT_KIND_REGISTRY[key];
1277
+ }
1278
+ var OrganizationModelBrandingSchema = z.object({
1279
+ organizationName: LabelSchema,
1280
+ productName: LabelSchema,
1281
+ shortName: z.string().trim().min(1).max(40),
1282
+ description: DescriptionSchema.optional(),
1283
+ logos: z.object({
1284
+ light: z.string().trim().min(1).max(2048).optional(),
1285
+ dark: z.string().trim().min(1).max(2048).optional()
1286
+ }).default({})
1287
+ });
1288
+ var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
1289
+ organizationName: "Default Organization",
1290
+ productName: "Elevasis",
1291
+ shortName: "Elevasis",
1292
+ logos: {}
1293
+ };
1294
+ var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
1295
+ z.object({
1296
+ id: ModelIdSchema,
1297
+ label: LabelSchema,
1298
+ path: PathSchema,
1299
+ surfaceType: SurfaceTypeSchema,
1300
+ description: DescriptionSchema.optional(),
1301
+ enabled: z.boolean().default(true),
1302
+ devOnly: z.boolean().optional(),
1303
+ icon: IconNameSchema.optional(),
1304
+ systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
1305
+ entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
1306
+ resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
1307
+ actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
1308
+ parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
1309
+ });
1310
+ var SidebarSurfaceTargetsSchema = z.object({
1311
+ systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
1312
+ entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
1313
+ resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
1314
+ actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
1315
+ }).default({});
1316
+ var SidebarNodeSchema = z.lazy(
1317
+ () => z.discriminatedUnion("type", [
1318
+ z.object({
1319
+ type: z.literal("group"),
1320
+ label: LabelSchema,
1321
+ description: DescriptionSchema.optional(),
1322
+ icon: IconNameSchema.optional(),
1323
+ order: z.number().int().optional(),
1324
+ children: z.record(z.string(), SidebarNodeSchema).default({})
1325
+ }),
1326
+ z.object({
1327
+ type: z.literal("surface"),
1328
+ label: LabelSchema,
1329
+ path: PathSchema,
1330
+ surfaceType: SurfaceTypeSchema,
1331
+ description: DescriptionSchema.optional(),
1332
+ icon: IconNameSchema.optional(),
1333
+ order: z.number().int().optional(),
1334
+ targets: SidebarSurfaceTargetsSchema.optional(),
1335
+ devOnly: z.boolean().optional(),
1336
+ requiresAdmin: z.boolean().optional()
1337
+ })
1338
+ ])
1339
+ );
1340
+ var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
1341
+ var SidebarNavigationSchema = z.object({
1342
+ primary: SidebarSectionSchema,
1343
+ bottom: SidebarSectionSchema
1344
+ }).default({ primary: {}, bottom: {} });
1345
+ var OrganizationModelNavigationSchema = z.object({
1346
+ sidebar: SidebarNavigationSchema
1347
+ }).default({ sidebar: { primary: {}, bottom: {} } });
1348
+ z.object({
1349
+ id: ModelIdSchema,
1350
+ label: LabelSchema,
1351
+ placement: z.string().trim().min(1).max(50),
1352
+ surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
1353
+ });
1354
+ var BusinessHoursDaySchema = z.object({
1355
+ open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
1356
+ close: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format")
1357
+ });
1358
+ var BusinessHoursSchema = z.object({
1359
+ monday: BusinessHoursDaySchema.optional(),
1360
+ tuesday: BusinessHoursDaySchema.optional(),
1361
+ wednesday: BusinessHoursDaySchema.optional(),
1362
+ thursday: BusinessHoursDaySchema.optional(),
1363
+ friday: BusinessHoursDaySchema.optional(),
1364
+ saturday: BusinessHoursDaySchema.optional(),
1365
+ sunday: BusinessHoursDaySchema.optional()
1366
+ }).default({});
1367
+ var IdentityDomainSchema = z.object({
1368
+ /** Why the organization exists — one or two plain-language sentences. */
1369
+ mission: z.string().trim().max(1e3).default(""),
1370
+ /** Long-term direction the organization is moving toward. */
1371
+ vision: z.string().trim().max(1e3).default(""),
1372
+ /** Legal registered name of the entity. */
1373
+ legalName: z.string().trim().max(200).default(""),
1374
+ /**
1375
+ * Type of legal entity (e.g. "LLC", "Corporation", "Sole Proprietor",
1376
+ * "Non-profit"). Free-form string so it covers any jurisdiction.
1377
+ */
1378
+ entityType: z.string().trim().max(100).default(""),
1379
+ /**
1380
+ * Primary jurisdiction of registration or operation
1381
+ * (e.g. "United States – Delaware", "Canada – Ontario").
1382
+ */
1383
+ jurisdiction: z.string().trim().max(200).default(""),
1384
+ /**
1385
+ * Industry category — broad classification (e.g. "Marketing Agency",
1386
+ * "Software / SaaS", "Professional Services").
1387
+ */
1388
+ industryCategory: z.string().trim().max(200).default(""),
1389
+ /**
1390
+ * Geographic focus — where the organization primarily operates or serves
1391
+ * (e.g. "North America", "Global", "Southeast Asia").
1392
+ */
1393
+ geographicFocus: z.string().trim().max(200).default(""),
1394
+ /**
1395
+ * IANA timezone identifier for the organization's primary operating timezone
1396
+ * (e.g. "America/Los_Angeles", "Europe/London", "UTC").
1397
+ */
1398
+ timeZone: z.string().trim().max(100).default("UTC"),
1399
+ /** Typical operating hours per day of week. Empty object means not configured. */
1400
+ businessHours: BusinessHoursSchema,
1401
+ /**
1402
+ * Long-form markdown capturing client context, problem narrative, and domain
1403
+ * background. Populated by /setup; surfaced to agents as organizational context.
1404
+ * Optional — many projects have no external client.
1405
+ */
1406
+ clientBrief: z.string().trim().default("")
1407
+ });
1408
+ var DEFAULT_ORGANIZATION_MODEL_IDENTITY = {
1409
+ mission: "",
1410
+ vision: "",
1411
+ legalName: "",
1412
+ entityType: "",
1413
+ jurisdiction: "",
1414
+ industryCategory: "",
1415
+ geographicFocus: "",
1416
+ timeZone: "UTC",
1417
+ businessHours: {},
1418
+ clientBrief: ""
1419
+ };
1420
+ var FirmographicsSchema = z.object({
1421
+ /** Industry vertical (e.g. "Marketing Agency", "Legal", "Real Estate"). */
1422
+ industry: z.string().trim().max(200).optional(),
1423
+ /**
1424
+ * Company headcount band (e.g. "1–10", "11–50", "51–200", "200+").
1425
+ * Free-form string to accommodate any band notation.
1426
+ */
1427
+ companySize: z.string().trim().max(100).optional(),
1428
+ /**
1429
+ * Primary geographic region the segment operates in or is targeted from
1430
+ * (e.g. "North America", "Europe", "Global").
1431
+ */
1432
+ region: z.string().trim().max(200).optional()
1433
+ });
1434
+ var CustomerSegmentSchema = z.object({
1435
+ /** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
1436
+ id: z.string().trim().min(1).max(100),
1437
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1438
+ order: z.number(),
1439
+ /** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
1440
+ name: z.string().trim().max(200).default(""),
1441
+ /** One or two sentences describing who this segment is. */
1442
+ description: z.string().trim().max(2e3).default(""),
1443
+ /**
1444
+ * The primary job(s) this segment is trying to get done — the goal they hire
1445
+ * a product/service to accomplish. Plain-language narrative or bullet list.
1446
+ */
1447
+ jobsToBeDone: z.string().trim().max(2e3).default(""),
1448
+ /**
1449
+ * Pains — frustrations, obstacles, and risks the segment experiences
1450
+ * when trying to accomplish their jobs-to-be-done.
1451
+ */
1452
+ pains: z.array(z.string().trim().max(500)).default([]),
1453
+ /**
1454
+ * Gains — outcomes and benefits the segment desires; positive motivators
1455
+ * beyond merely resolving pains.
1456
+ */
1457
+ gains: z.array(z.string().trim().max(500)).default([]),
1458
+ /** Firmographic profile for targeting and filtering. */
1459
+ firmographics: FirmographicsSchema.default({}),
1460
+ /**
1461
+ * Value proposition — one or two sentences stating why this organization's
1462
+ * offering is uniquely suited for this segment's needs.
1463
+ */
1464
+ valueProp: z.string().trim().max(2e3).default("")
1465
+ });
1466
+ var CustomersDomainSchema = z.record(z.string(), CustomerSegmentSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1467
+ message: "Each segment entry id must match its map key"
1468
+ }).default({});
1469
+ var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {};
1470
+ var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]).meta({ label: "Pricing model", color: "green" });
1471
+ var ProductSchema = z.object({
1472
+ /** Stable unique identifier for the product (e.g. "product-starter-plan"). */
1473
+ id: z.string().trim().min(1).max(100),
1474
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1475
+ order: z.number(),
1476
+ /** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
1477
+ name: z.string().trim().max(200).default(""),
1478
+ /** One or two sentences describing what this product/service delivers. */
1479
+ description: z.string().trim().max(2e3).default(""),
1480
+ /**
1481
+ * How this product is priced:
1482
+ * - "one-time" — single purchase (setup fee, project fee)
1483
+ * - "subscription" — recurring (monthly/annual SaaS, retainer)
1484
+ * - "usage-based" — metered by consumption (API calls, seats)
1485
+ * - "custom" — negotiated or bespoke pricing
1486
+ */
1487
+ pricingModel: PricingModelSchema.default("custom"),
1488
+ /** Base price amount (≥ 0). Currency unit defined by `currency`. */
1489
+ price: z.number().min(0).default(0),
1490
+ /**
1491
+ * ISO 4217 currency code (e.g. "USD", "EUR", "GBP").
1492
+ * Free-form string to accommodate any currency; defaults to "USD".
1493
+ */
1494
+ currency: z.string().trim().max(10).default("USD"),
1495
+ /**
1496
+ * IDs of customer segments this product targets.
1497
+ * Each id must reference a declared `customers.segments[].id`.
1498
+ * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
1499
+ */
1500
+ targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
1501
+ /**
1502
+ * Optional: ID of the platform system responsible for delivering this product.
1503
+ * When present, must reference a declared `systems.systems[].id`.
1504
+ * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
1505
+ */
1506
+ deliveryFeatureId: z.string().trim().min(1).optional()
1507
+ });
1508
+ var OfferingsDomainSchema = z.record(z.string(), ProductSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1509
+ message: "Each product entry id must match its map key"
1510
+ }).default({});
1511
+ var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {};
1512
+ z.enum(["workflow", "agent", "integration", "script"]).meta({ label: "Resource kind", color: "orange" });
1513
+ var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Governance status", color: "teal" });
1514
+ var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "platform"]).meta({ label: "Agent kind", color: "violet" });
1515
+ var ScriptResourceLanguageSchema = z.enum(["shell", "sql", "typescript", "python"]).meta({ label: "Language" });
1516
+ var CodeReferenceRoleSchema = z.enum(["entrypoint", "handler", "schema", "test", "docs", "config"]).meta({ label: "Code reference role", color: "blue" });
1517
+ 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");
1518
+ var EventIdSchema = z.string().trim().min(1).max(300).regex(
1519
+ /^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*:[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
1520
+ "Event IDs must use <owner-id>:<event-key>"
1521
+ );
1522
+ var EventKeySchema = ModelIdSchema;
1523
+ var EventEmissionDescriptorSchema = z.object({
1524
+ eventKey: EventKeySchema,
1525
+ label: z.string().trim().min(1).max(120),
1526
+ payloadSchema: ModelIdSchema.optional(),
1527
+ lifecycle: SystemLifecycleSchema.optional()
1528
+ });
1529
+ EventEmissionDescriptorSchema.extend({
1530
+ id: EventIdSchema,
1531
+ ownerId: z.union([ResourceIdSchema, ModelIdSchema]),
1532
+ ownerKind: z.enum(["resource", "entity"]).meta({ label: "Owner kind" })
1533
+ });
1534
+ var ResourceOntologyBindingSchema = z.object({
1535
+ actions: z.array(OntologyIdSchema).optional(),
1536
+ primaryAction: OntologyIdSchema.optional(),
1537
+ reads: z.array(OntologyIdSchema).optional(),
1538
+ writes: z.array(OntologyIdSchema).optional(),
1539
+ usesCatalogs: z.array(OntologyIdSchema).optional(),
1540
+ emits: z.array(OntologyIdSchema).optional()
1541
+ }).superRefine((binding, ctx) => {
1542
+ if (binding.primaryAction === void 0) return;
1543
+ if (binding.actions?.includes(binding.primaryAction)) return;
1544
+ ctx.addIssue({
1545
+ code: z.ZodIssueCode.custom,
1546
+ path: ["primaryAction"],
1547
+ message: "Resource ontology primaryAction must be included in actions"
1548
+ });
1549
+ });
1550
+ var CodeReferenceSchema = z.object({
1551
+ path: z.string().trim().min(1).max(500).regex(/^[A-Za-z0-9_./$@()[\] -]+$/, "Code reference paths must be repo-relative paths"),
1552
+ role: CodeReferenceRoleSchema,
1553
+ symbol: z.string().trim().min(1).max(200).optional(),
1554
+ description: z.string().trim().min(1).max(300).optional()
1555
+ });
1556
+ var ResourceEntryBaseSchema = z.object({
1557
+ /** Canonical resource id; runtime resourceId derives from this value. */
1558
+ id: ResourceIdSchema,
1559
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1560
+ order: z.number().default(0),
1561
+ /** Required single System membership — value is a dot-separated system path (e.g. "sales.lead-gen"). */
1562
+ systemPath: SystemPathSchema.meta({ ref: "system" }),
1563
+ /** Executable display title owned by the OM Resource descriptor. */
1564
+ title: LabelSchema.optional(),
1565
+ /** Executable display description owned by the OM Resource descriptor. */
1566
+ description: DescriptionSchema.optional(),
1567
+ /** Optional role responsible for maintaining this resource. */
1568
+ ownerRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
1569
+ status: ResourceGovernanceStatusSchema,
1570
+ /**
1571
+ * Ontology contract bindings for the semantic work this resource performs.
1572
+ * `emits` stays nested here so top-level resource emits descriptors remain
1573
+ * compatible with graph event projection during the bridge.
1574
+ */
1575
+ ontology: ResourceOntologyBindingSchema.optional(),
1576
+ /** Repo-relative implementation breadcrumbs for agents and operators. */
1577
+ codeRefs: z.array(CodeReferenceSchema).default([])
1578
+ });
1579
+ var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
1580
+ kind: z.literal("workflow"),
1581
+ emits: z.array(EventEmissionDescriptorSchema).optional()
1582
+ });
1583
+ var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
1584
+ kind: z.literal("agent"),
1585
+ /** Mirrors code-side AgentConfig.kind. */
1586
+ agentKind: AgentKindSchema,
1587
+ /** Role this agent embodies, if any. */
1588
+ actsAsRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
1589
+ /** Mirrors AgentConfig.sessionCapable. */
1590
+ sessionCapable: z.boolean(),
1591
+ /** Broad/composite callable entry points orchestrated by this agent. */
1592
+ invocations: z.array(ActionInvocationSchema).default([]),
1593
+ emits: z.array(EventEmissionDescriptorSchema).optional()
1594
+ });
1595
+ var IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
1596
+ kind: z.literal("integration"),
1597
+ provider: z.string().trim().min(1).max(100)
1598
+ });
1599
+ var ScriptResourceSourceSchema = z.union([
1600
+ z.string().trim().min(1).max(5e4),
1601
+ z.object({
1602
+ file: z.string().trim().min(1).max(500)
1603
+ })
1604
+ ]);
1605
+ var ScriptResourceEntrySchema = ResourceEntryBaseSchema.extend({
1606
+ kind: z.literal("script"),
1607
+ language: ScriptResourceLanguageSchema,
1608
+ source: ScriptResourceSourceSchema
1609
+ });
1610
+ var ResourceEntrySchema = z.discriminatedUnion("kind", [
1611
+ WorkflowResourceEntrySchema,
1612
+ AgentResourceEntrySchema,
1613
+ IntegrationResourceEntrySchema,
1614
+ ScriptResourceEntrySchema
1615
+ ]);
1616
+ var ResourcesDomainSchema = z.record(z.string(), ResourceEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1617
+ message: "Each resource entry id must match its map key"
1618
+ }).default({});
1619
+ var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {};
1620
+ function defineResource(resource) {
1621
+ return ResourceEntrySchema.parse(resource);
1622
+ }
1623
+ function defineResources(resources) {
1624
+ return Object.fromEntries(
1625
+ Object.entries(resources).map(([key, resource]) => [key, ResourceEntrySchema.parse(resource)])
1626
+ );
1627
+ }
1628
+ function ontologyIdFrom(input) {
1629
+ return typeof input === "string" ? input : input.id;
1630
+ }
1631
+ function ontologyIdArrayFrom(input) {
1632
+ return input?.map(ontologyIdFrom);
1633
+ }
1634
+ function defineResourceOntology(input) {
1635
+ return ResourceOntologyBindingSchema.parse({
1636
+ actions: ontologyIdArrayFrom(input.actions),
1637
+ primaryAction: input.primaryAction === void 0 ? void 0 : ontologyIdFrom(input.primaryAction),
1638
+ reads: ontologyIdArrayFrom(input.reads),
1639
+ writes: ontologyIdArrayFrom(input.writes),
1640
+ usesCatalogs: ontologyIdArrayFrom(input.usesCatalogs),
1641
+ emits: ontologyIdArrayFrom(input.emits)
1642
+ });
1643
+ }
1644
+
1645
+ // ../core/src/organization-model/domains/roles.ts
1646
+ var RoleIdSchema = ModelIdSchema;
1647
+ var HumanRoleHolderSchema = z.object({
1648
+ kind: z.literal("human"),
1649
+ userId: z.string().trim().min(1).max(200)
1650
+ });
1651
+ var AgentRoleHolderSchema = z.object({
1652
+ kind: z.literal("agent"),
1653
+ agentId: ResourceIdSchema.meta({ ref: "resource" })
1654
+ });
1655
+ var TeamRoleHolderSchema = z.object({
1656
+ kind: z.literal("team"),
1657
+ memberIds: z.array(z.string().trim().min(1).max(200)).min(1)
1658
+ });
1659
+ var RoleHolderSchema = z.discriminatedUnion("kind", [
1660
+ HumanRoleHolderSchema,
1661
+ AgentRoleHolderSchema,
1662
+ TeamRoleHolderSchema
1663
+ ]);
1664
+ var RoleHoldersSchema = z.union([RoleHolderSchema, z.array(RoleHolderSchema).min(1)]);
1665
+ var RoleSchema = z.object({
1666
+ /** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
1667
+ id: RoleIdSchema,
1668
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1669
+ order: z.number(),
1670
+ /** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
1671
+ title: z.string().trim().min(1).max(200),
1672
+ /**
1673
+ * List of responsibilities this role owns - plain-language descriptions of
1674
+ * what the person in this role is accountable for delivering.
1675
+ * Defaults to empty array so minimal role definitions stay concise.
1676
+ */
1677
+ responsibilities: z.array(z.string().trim().max(500)).default([]),
1678
+ /**
1679
+ * Optional: ID of another role this role reports to.
1680
+ * When present, must reference another `roles[].id` in the same organization.
1681
+ */
1682
+ reportsToId: RoleIdSchema.meta({ ref: "role" }).optional(),
1683
+ /**
1684
+ * Optional: human, agent, or team holder currently filling this role.
1685
+ * Agent holders reference OM Resource IDs and are validated at the model level.
1686
+ */
1687
+ heldBy: RoleHoldersSchema.optional(),
1688
+ /**
1689
+ * Optional Systems this role is accountable for.
1690
+ * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
1691
+ */
1692
+ responsibleFor: z.array(SystemIdSchema.meta({ ref: "system" })).optional()
1693
+ });
1694
+ var RolesDomainSchema = z.record(z.string(), RoleSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1695
+ message: "Each role entry id must match its map key"
1696
+ }).default({});
1697
+ var DEFAULT_ORGANIZATION_MODEL_ROLES = {};
1698
+ var KeyResultSchema = z.object({
1699
+ /** Stable unique identifier for the measurable outcome (e.g. "kr-revenue-q1"). */
1700
+ id: z.string().trim().min(1).max(100),
1701
+ /** Plain-language description of this measurable outcome (e.g. "Increase trial-to-paid conversion"). */
1702
+ description: z.string().trim().min(1).max(500),
1703
+ /**
1704
+ * What is being measured — the metric name (e.g. "monthly revenue", "NPS score",
1705
+ * "trial-to-paid conversion rate"). Free-form string.
1706
+ */
1707
+ targetMetric: z.string().trim().min(1).max(200),
1708
+ /** Current measured value. Defaults to 0 when not yet tracked. */
1709
+ currentValue: z.number().default(0),
1710
+ /**
1711
+ * Target value to reach for this measurable outcome to be considered achieved.
1712
+ * Optional — omit if the outcome is directional (e.g. "reduce churn") without
1713
+ * a hard numeric target.
1714
+ */
1715
+ targetValue: z.number().optional()
1716
+ });
1717
+ var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
1718
+ var ObjectiveSchema = z.object({
1719
+ /** Stable unique identifier for the goal (e.g. "goal-grow-arr-q1-2026"). */
1720
+ id: z.string().trim().min(1).max(100),
1721
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1722
+ order: z.number(),
1723
+ /** Plain-language description of what the organization wants to achieve. */
1724
+ description: z.string().trim().min(1).max(1e3),
1725
+ /**
1726
+ * Start of the period this goal is active for — ISO 8601 date string (YYYY-MM-DD).
1727
+ * Must be strictly before `periodEnd`.
1728
+ */
1729
+ periodStart: z.string().regex(ISO_DATE_REGEX, "periodStart must be an ISO date string (YYYY-MM-DD)"),
1730
+ /**
1731
+ * End of the period this goal is active for — ISO 8601 date string (YYYY-MM-DD).
1732
+ * Must be strictly after `periodStart`.
1733
+ * Enforced via `OrganizationModelSchema.superRefine()`.
1734
+ */
1735
+ periodEnd: z.string().regex(ISO_DATE_REGEX, "periodEnd must be an ISO date string (YYYY-MM-DD)"),
1736
+ /**
1737
+ * List of measurable outcomes that define success for this goal.
1738
+ * Defaults to empty array so goals can be declared before outcomes are defined.
1739
+ */
1740
+ keyResults: z.array(KeyResultSchema).default([])
1741
+ });
1742
+ var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1743
+ message: "Each objective entry id must match its map key"
1744
+ }).default({});
1745
+ var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
1746
+ var KnowledgeTargetKindSchema = z.enum([
1747
+ "system",
1748
+ "resource",
1749
+ "knowledge",
1750
+ "stage",
1751
+ "action",
1752
+ "role",
1753
+ "goal",
1754
+ "customer-segment",
1755
+ "offering",
1756
+ "ontology",
1757
+ // D4: content nodes are a valid knowledge target after compound-domain data moved into system.content
1758
+ "content-node"
1759
+ ]).meta({ label: "Target kind" });
1760
+ var KnowledgeTargetRefSchema = z.object({
1761
+ kind: KnowledgeTargetKindSchema,
1762
+ // D4: content-node targets use a qualified id format '<system-path>:<local-content-id>'.
1763
+ // Ontology targets use the canonical '<scope>:<kind>/<local-id>' ontology id format.
1764
+ // Business-logic validation of target existence is done in OrganizationModelSchema.superRefine.
1765
+ id: z.string().trim().min(1).max(300)
1766
+ }).superRefine((target, ctx) => {
1767
+ if (target.kind !== "ontology") return;
1768
+ const result = OntologyIdSchema.safeParse(target.id);
1769
+ if (!result.success) {
1770
+ ctx.addIssue({
1771
+ code: z.ZodIssueCode.custom,
1772
+ path: ["id"],
1773
+ message: "Ontology knowledge targets must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
1774
+ });
1775
+ }
1776
+ });
1777
+ var LegacyKnowledgeLinkSchema = z.object({
1778
+ nodeId: z.union([NodeIdStringSchema, z.templateLiteral(["ontology:", OntologyIdSchema])])
1779
+ });
1780
+ var CanonicalKnowledgeLinkSchema = z.object({
1781
+ target: KnowledgeTargetRefSchema
1782
+ });
1783
+ function nodeIdFromTarget(target) {
1784
+ return `${target.kind}:${target.id}`;
1785
+ }
1786
+ function targetFromNodeId(nodeId) {
1787
+ const [kind, ...idParts] = nodeId.split(":");
1788
+ return {
1789
+ kind: KnowledgeTargetKindSchema.parse(kind),
1790
+ id: idParts.join(":")
1791
+ };
1792
+ }
1793
+ var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
1794
+ const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
1795
+ return {
1796
+ target,
1797
+ nodeId: nodeIdFromTarget(target)
1798
+ };
1799
+ });
1800
+ var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
1801
+ var OrgKnowledgeNodeSchema = z.object({
1802
+ id: ModelIdSchema,
1803
+ kind: OrgKnowledgeKindSchema,
1804
+ title: z.string().trim().min(1).max(200),
1805
+ summary: z.string().trim().min(1).max(1e3),
1806
+ icon: IconNameSchema.optional(),
1807
+ /** Canonical documentation URL when body content is a local summary. */
1808
+ externalUrl: z.string().trim().url().max(500).optional(),
1809
+ /** Optional generated source file path for local MDX-backed knowledge nodes. */
1810
+ sourceFilePath: z.string().trim().min(1).max(500).optional(),
1811
+ /** Raw MDX string. Phase 2 will introduce a structured block format. */
1812
+ body: z.string().trim().min(1),
1813
+ /**
1814
+ * Graph links to other OM nodes this knowledge node governs.
1815
+ * Each link emits a `governs` edge: knowledge-node -> target node.
1816
+ */
1817
+ links: z.array(KnowledgeLinkSchema).default([]),
1818
+ /** Role identifiers that own this knowledge node. */
1819
+ ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
1820
+ /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
1821
+ updatedAt: z.string().trim().min(1).max(50)
1822
+ });
1823
+ var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
1824
+ var SecretLikeMetadataKeySchema = /(?:secret|password|passwd|token|api[-_]?key|credential|private[-_]?key)/i;
1825
+ 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-----)/;
1826
+ var OmTopologyNodeKindSchema = z.enum([
1827
+ "system",
1828
+ "resource",
1829
+ "ontology",
1830
+ "policy",
1831
+ "role",
1832
+ "trigger",
1833
+ "humanCheckpoint",
1834
+ "externalResource"
1835
+ ]);
1836
+ var OmTopologyRelationshipKindSchema = z.enum(["triggers", "uses", "approval"]);
1837
+ var OmTopologyNodeRefSchema = z.discriminatedUnion("kind", [
1838
+ z.object({ kind: z.literal("system"), id: ModelIdSchema }),
1839
+ z.object({ kind: z.literal("resource"), id: ResourceIdSchema }),
1840
+ z.object({ kind: z.literal("ontology"), id: OntologyIdSchema }),
1841
+ z.object({ kind: z.literal("policy"), id: ModelIdSchema }),
1842
+ z.object({ kind: z.literal("role"), id: ModelIdSchema }),
1843
+ z.object({ kind: z.literal("trigger"), id: ResourceIdSchema }),
1844
+ z.object({ kind: z.literal("humanCheckpoint"), id: ResourceIdSchema }),
1845
+ z.object({ kind: z.literal("externalResource"), id: ResourceIdSchema })
1846
+ ]);
1847
+ var OmTopologyMetadataSchema = z.record(z.string().trim().min(1).max(120), JsonValueSchema).superRefine((metadata, ctx) => {
1848
+ function visit(value, path) {
1849
+ if (typeof value === "string" && SecretLikeMetadataValueSchema.test(value)) {
1850
+ ctx.addIssue({
1851
+ code: z.ZodIssueCode.custom,
1852
+ path,
1853
+ message: "Topology metadata must not contain secret-like values"
1854
+ });
1855
+ return;
1856
+ }
1857
+ if (Array.isArray(value)) {
1858
+ value.forEach((entry, index) => visit(entry, [...path, index]));
1859
+ return;
1860
+ }
1861
+ if (typeof value !== "object" || value === null) return;
1862
+ Object.entries(value).forEach(([key, entry]) => {
1863
+ if (SecretLikeMetadataKeySchema.test(key)) {
1864
+ ctx.addIssue({
1865
+ code: z.ZodIssueCode.custom,
1866
+ path: [...path, key],
1867
+ message: `Topology metadata key "${key}" looks secret-like`
1868
+ });
1869
+ }
1870
+ visit(entry, [...path, key]);
1871
+ });
1872
+ }
1873
+ visit(metadata, []);
1874
+ });
1875
+ var OmTopologyRelationshipSchema = z.object({
1876
+ from: OmTopologyNodeRefSchema,
1877
+ kind: OmTopologyRelationshipKindSchema,
1878
+ to: OmTopologyNodeRefSchema,
1879
+ systemPath: SystemPathSchema.optional(),
1880
+ required: z.boolean().optional(),
1881
+ metadata: OmTopologyMetadataSchema.optional()
1882
+ });
1883
+ var OmTopologyDomainSchema = z.object({
1884
+ version: z.literal(1).default(1),
1885
+ relationships: z.record(z.string().trim().min(1).max(255), OmTopologyRelationshipSchema).default({})
1886
+ }).default({ version: 1, relationships: {} });
1887
+ var DEFAULT_ORGANIZATION_MODEL_TOPOLOGY = {
1888
+ version: 1,
1889
+ relationships: {}
1890
+ };
1891
+ function idFrom(input) {
1892
+ return typeof input === "string" ? input : input.id;
1893
+ }
1894
+ function parseRef(kind, id) {
1895
+ return OmTopologyNodeRefSchema.parse({ kind, id });
1896
+ }
1897
+ function isNodeRef(input) {
1898
+ return OmTopologyNodeRefSchema.safeParse(input).success;
1899
+ }
1900
+ function isResourceEntry(input) {
1901
+ if (typeof input !== "object" || input === null) return false;
1902
+ const candidate = input;
1903
+ return typeof candidate.id === "string" && typeof candidate.systemPath === "string" && typeof candidate.status === "string" && ["workflow", "agent", "integration", "script"].includes(String(candidate.kind));
1904
+ }
1905
+ var topologyRef = {
1906
+ system: (system) => parseRef("system", idFrom(system)),
1907
+ resource: (resource) => parseRef("resource", idFrom(resource)),
1908
+ ontology: (record) => parseRef("ontology", idFrom(record)),
1909
+ policy: (policy) => parseRef("policy", idFrom(policy)),
1910
+ role: (role) => parseRef("role", idFrom(role)),
1911
+ trigger: (trigger) => parseRef("trigger", idFrom(trigger)),
1912
+ humanCheckpoint: (checkpoint) => parseRef("humanCheckpoint", idFrom(checkpoint)),
1913
+ externalResource: (externalResource) => parseRef("externalResource", idFrom(externalResource))
1914
+ };
1915
+ var topologyRelationship = {
1916
+ triggers: (from, to, options = {}) => defineTopologyRelationship({
1917
+ ...options,
1918
+ from,
1919
+ kind: "triggers",
1920
+ to
1921
+ }),
1922
+ uses: (from, to, options = {}) => defineTopologyRelationship({
1923
+ ...options,
1924
+ from,
1925
+ kind: "uses",
1926
+ to
1927
+ }),
1928
+ approval: (from, to, options = {}) => defineTopologyRelationship({
1929
+ ...options,
1930
+ from,
1931
+ kind: "approval",
1932
+ to
1933
+ }),
1934
+ usesIntegration: (from, integration, options = {}) => defineTopologyRelationship({
1935
+ required: true,
1936
+ ...options,
1937
+ from,
1938
+ kind: "uses",
1939
+ to: integration
1940
+ }),
1941
+ requestsApproval: (from, checkpoint, options = {}) => defineTopologyRelationship({
1942
+ required: true,
1943
+ ...options,
1944
+ from,
1945
+ kind: "approval",
1946
+ to: topologyRef.humanCheckpoint(checkpoint)
1947
+ }),
1948
+ checkpointRoutesTo: (checkpoint, to, options = {}) => defineTopologyRelationship({
1949
+ required: true,
1950
+ ...options,
1951
+ from: topologyRef.humanCheckpoint(checkpoint),
1952
+ kind: "triggers",
1953
+ to
1954
+ })
1955
+ };
1956
+ function compileTopologyNodeRef(input) {
1957
+ if (isNodeRef(input)) return input;
1958
+ if (isResourceEntry(input)) return topologyRef.resource(input);
1959
+ throw new Error("Topology node refs must be typed node objects or serializable { kind, id } refs");
1960
+ }
1961
+ function parseTopologyNodeRef(input) {
1962
+ if (typeof input !== "string") return OmTopologyNodeRefSchema.parse(input);
1963
+ const separatorIndex = input.indexOf(":");
1964
+ if (separatorIndex === -1) {
1965
+ throw new Error(`Topology node ref "${input}" must use <kind>:<id>`);
1966
+ }
1967
+ const kind = input.slice(0, separatorIndex);
1968
+ const id = input.slice(separatorIndex + 1);
1969
+ if (!OmTopologyNodeKindSchema.safeParse(kind).success) {
1970
+ throw new Error(`Topology node ref "${input}" has unsupported kind "${kind}"`);
1971
+ }
1972
+ return OmTopologyNodeRefSchema.parse({ kind, id });
1973
+ }
1974
+ function defineTopologyRelationship(input) {
1975
+ return OmTopologyRelationshipSchema.parse({
1976
+ ...input,
1977
+ from: compileTopologyNodeRef(input.from),
1978
+ to: compileTopologyNodeRef(input.to)
1979
+ });
1980
+ }
1981
+ function defineTopology(relationships) {
1982
+ const entries = Array.isArray(relationships) ? relationships.map((relationship, index) => [`relationship-${index + 1}`, relationship]) : Object.entries(relationships);
1983
+ return OmTopologyDomainSchema.parse({
1984
+ version: 1,
1985
+ relationships: Object.fromEntries(entries.map(([key, relationship]) => [key, defineTopologyRelationship(relationship)]))
1986
+ });
1987
+ }
1988
+ var PolicyIdSchema = ModelIdSchema;
1989
+ var PolicyApplicabilitySchema = z.object({
1990
+ systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
1991
+ actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
1992
+ resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
1993
+ roleIds: z.array(ModelIdSchema.meta({ ref: "role" })).default([])
1994
+ });
1995
+ var PolicyTriggerSchema = z.discriminatedUnion("kind", [
1996
+ z.object({
1997
+ kind: z.literal("event"),
1998
+ eventId: EventIdSchema.meta({ ref: "event" })
1999
+ }),
2000
+ z.object({
2001
+ kind: z.literal("action-invocation"),
2002
+ actionId: ModelIdSchema.meta({ ref: "action" })
2003
+ }),
2004
+ z.object({
2005
+ kind: z.literal("schedule"),
2006
+ cron: z.string().trim().min(1).max(120)
2007
+ }),
2008
+ z.object({
2009
+ kind: z.literal("manual")
2010
+ })
2011
+ ]);
2012
+ var PolicyPredicateSchema = z.discriminatedUnion("kind", [
2013
+ z.object({
2014
+ kind: z.literal("always")
2015
+ }),
2016
+ z.object({
2017
+ kind: z.literal("expression"),
2018
+ expression: z.string().trim().min(1).max(2e3)
2019
+ }),
2020
+ z.object({
2021
+ kind: z.literal("threshold"),
2022
+ metric: ModelIdSchema,
2023
+ operator: z.enum(["lt", "lte", "eq", "gte", "gt"]).meta({ label: "Operator" }),
2024
+ value: z.number()
2025
+ })
2026
+ ]);
2027
+ var PolicyEffectSchema = z.discriminatedUnion("kind", [
2028
+ z.object({
2029
+ kind: z.literal("require-approval"),
2030
+ roleId: ModelIdSchema.meta({ ref: "role" }).optional()
2031
+ }),
2032
+ z.object({
2033
+ kind: z.literal("invoke-action"),
2034
+ actionId: ModelIdSchema.meta({ ref: "action" })
2035
+ }),
2036
+ z.object({
2037
+ kind: z.literal("notify-role"),
2038
+ roleId: ModelIdSchema.meta({ ref: "role" })
2039
+ }),
2040
+ z.object({
2041
+ kind: z.literal("block")
2042
+ })
2043
+ ]);
2044
+ var PolicySchema = z.object({
2045
+ id: PolicyIdSchema,
2046
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
2047
+ order: z.number(),
2048
+ label: LabelSchema,
2049
+ description: DescriptionSchema.optional(),
2050
+ trigger: PolicyTriggerSchema,
2051
+ predicate: PolicyPredicateSchema.default({ kind: "always" }),
2052
+ actions: z.array(PolicyEffectSchema).min(1),
2053
+ appliesTo: PolicyApplicabilitySchema.default({
2054
+ systemIds: [],
2055
+ actionIds: [],
2056
+ resourceIds: [],
2057
+ roleIds: []
2058
+ }),
2059
+ lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
2060
+ });
2061
+ var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
2062
+ message: "Each policy entry id must match its map key"
2063
+ }).default({});
2064
+ var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
2065
+
2066
+ // ../core/src/organization-model/schema.ts
2067
+ z.enum([
2068
+ "branding",
2069
+ "identity",
2070
+ "customers",
2071
+ "offerings",
2072
+ "roles",
2073
+ "goals",
2074
+ "systems",
2075
+ "ontology",
2076
+ "resources",
2077
+ "topology",
2078
+ "actions",
2079
+ "entities",
2080
+ "policies",
2081
+ "knowledge"
2082
+ ]);
2083
+ var OrganizationModelDomainMetadataSchema = z.object({
2084
+ version: z.literal(1).default(1),
2085
+ lastModified: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "lastModified must be an ISO date string (YYYY-MM-DD)")
2086
+ });
2087
+ var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
2088
+ branding: { version: 1, lastModified: "2026-05-10" },
2089
+ identity: { version: 1, lastModified: "2026-05-10" },
2090
+ customers: { version: 1, lastModified: "2026-05-10" },
2091
+ offerings: { version: 1, lastModified: "2026-05-10" },
2092
+ roles: { version: 1, lastModified: "2026-05-10" },
2093
+ goals: { version: 1, lastModified: "2026-05-10" },
2094
+ systems: { version: 1, lastModified: "2026-05-10" },
2095
+ ontology: { version: 1, lastModified: "2026-05-14" },
2096
+ resources: { version: 1, lastModified: "2026-05-10" },
2097
+ topology: { version: 1, lastModified: "2026-05-14" },
2098
+ actions: { version: 1, lastModified: "2026-05-10" },
2099
+ entities: { version: 1, lastModified: "2026-05-10" },
2100
+ policies: { version: 1, lastModified: "2026-05-10" },
2101
+ knowledge: { version: 1, lastModified: "2026-05-10" }
2102
+ };
2103
+ var OrganizationModelDomainMetadataByDomainSchema = z.object({
2104
+ branding: OrganizationModelDomainMetadataSchema,
2105
+ identity: OrganizationModelDomainMetadataSchema,
2106
+ customers: OrganizationModelDomainMetadataSchema,
2107
+ offerings: OrganizationModelDomainMetadataSchema,
2108
+ roles: OrganizationModelDomainMetadataSchema,
2109
+ goals: OrganizationModelDomainMetadataSchema,
2110
+ systems: OrganizationModelDomainMetadataSchema,
2111
+ ontology: OrganizationModelDomainMetadataSchema,
2112
+ resources: OrganizationModelDomainMetadataSchema,
2113
+ topology: OrganizationModelDomainMetadataSchema,
2114
+ actions: OrganizationModelDomainMetadataSchema,
2115
+ entities: OrganizationModelDomainMetadataSchema,
2116
+ policies: OrganizationModelDomainMetadataSchema,
2117
+ knowledge: OrganizationModelDomainMetadataSchema
2118
+ }).partial().default(DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA).transform((metadata) => ({ ...DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, ...metadata }));
2119
+ var OrganizationModelSchemaBase = z.object({
2120
+ version: z.literal(1).default(1),
2121
+ domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
2122
+ branding: OrganizationModelBrandingSchema,
2123
+ navigation: OrganizationModelNavigationSchema,
2124
+ identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
2125
+ customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
2126
+ offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
2127
+ roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
2128
+ goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
2129
+ systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
2130
+ ontology: OntologyScopeSchema.default(DEFAULT_ONTOLOGY_SCOPE),
2131
+ resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
2132
+ topology: OmTopologyDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_TOPOLOGY),
2133
+ actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
2134
+ entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
2135
+ policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
2136
+ // D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
2137
+ knowledge: KnowledgeDomainSchema.default({})
2138
+ });
2139
+ function addIssue(ctx, path, message) {
2140
+ ctx.addIssue({
2141
+ code: z.ZodIssueCode.custom,
2142
+ path,
2143
+ message
2144
+ });
2145
+ }
2146
+ function isLifecycleEnabled(lifecycle, enabled) {
2147
+ if (enabled === false) return false;
2148
+ return lifecycle !== "deprecated" && lifecycle !== "archived";
2149
+ }
2150
+ function defaultSystemPathFor(id) {
2151
+ return `/${id.replaceAll(".", "/")}`;
2152
+ }
2153
+ function asRoleHolderArray(heldBy) {
2154
+ return Array.isArray(heldBy) ? heldBy : [heldBy];
2155
+ }
2156
+ function isKnowledgeKindCompatibleWithTarget(knowledgeKind, targetKind) {
2157
+ if (knowledgeKind === "reference") return true;
2158
+ if (knowledgeKind === "playbook") {
2159
+ return ["system", "resource", "stage", "action", "ontology"].includes(targetKind);
2160
+ }
2161
+ if (knowledgeKind === "strategy") {
2162
+ return ["system", "goal", "offering", "customer-segment", "ontology"].includes(targetKind);
2163
+ }
2164
+ return false;
2165
+ }
2166
+ function isRecord(value) {
2167
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2168
+ }
2169
+ OrganizationModelSchemaBase.superRefine((model, ctx) => {
2170
+ function collectAllSystems(systems, prefix = "", schemaPath = ["systems"]) {
2171
+ const result = [];
2172
+ for (const [key, system] of Object.entries(systems)) {
2173
+ const path = prefix ? `${prefix}.${key}` : key;
2174
+ const currentSchemaPath = [...schemaPath, key];
2175
+ result.push({ path, schemaPath: currentSchemaPath, system });
2176
+ const childSystems = system.systems ?? system.subsystems;
2177
+ if (childSystems !== void 0) {
2178
+ result.push(
2179
+ ...collectAllSystems(childSystems, path, [...currentSchemaPath, system.systems !== void 0 ? "systems" : "subsystems"])
2180
+ );
2181
+ }
2182
+ }
2183
+ return result;
2184
+ }
2185
+ const allSystems = collectAllSystems(model.systems);
2186
+ const systemsById = /* @__PURE__ */ new Map();
2187
+ for (const { path, system } of allSystems) {
2188
+ systemsById.set(path, system);
2189
+ systemsById.set(system.id, system);
2190
+ }
2191
+ const systemIdsByEffectivePath = /* @__PURE__ */ new Map();
2192
+ allSystems.forEach(({ path, schemaPath, system }) => {
2193
+ if (system.parentSystemId !== void 0 && !systemsById.has(system.parentSystemId)) {
2194
+ addIssue(
2195
+ ctx,
2196
+ [...schemaPath, "parentSystemId"],
2197
+ `System "${system.id}" references unknown parent "${system.parentSystemId}"`
2198
+ );
2199
+ }
2200
+ const hasChildren = Object.keys(system.systems ?? system.subsystems ?? {}).length > 0 || allSystems.some((candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes("."));
2201
+ const contributesRoutePath = system.ui?.path !== void 0 || system.path !== void 0 || !hasChildren;
2202
+ if (contributesRoutePath) {
2203
+ const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path);
2204
+ const existingSystemId = systemIdsByEffectivePath.get(effectivePath);
2205
+ if (existingSystemId !== void 0) {
2206
+ addIssue(
2207
+ ctx,
2208
+ [...schemaPath, system.ui?.path !== void 0 ? "ui" : "path"],
2209
+ `System "${path}" effective path "${effectivePath}" duplicates system "${existingSystemId}"`
2210
+ );
2211
+ } else {
2212
+ systemIdsByEffectivePath.set(effectivePath, path);
2213
+ }
2214
+ }
2215
+ if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
2216
+ const hasEnabledDescendant = Object.values(system.systems ?? system.subsystems ?? {}).some(
2217
+ (candidate) => isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
2218
+ ) || allSystems.some(
2219
+ (candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
2220
+ );
2221
+ if (!hasEnabledDescendant) {
2222
+ addIssue(
2223
+ ctx,
2224
+ [...schemaPath, "lifecycle"],
2225
+ `System "${path}" is active but has no active descendants`
2226
+ );
2227
+ }
2228
+ }
2229
+ });
2230
+ allSystems.forEach(({ schemaPath, system }) => {
2231
+ const visited = /* @__PURE__ */ new Set();
2232
+ let currentParentId = system.parentSystemId;
2233
+ while (currentParentId !== void 0) {
2234
+ if (currentParentId === system.id || visited.has(currentParentId)) {
2235
+ addIssue(ctx, [...schemaPath, "parentSystemId"], `System "${system.id}" has a parent cycle`);
2236
+ return;
2237
+ }
2238
+ visited.add(currentParentId);
2239
+ currentParentId = systemsById.get(currentParentId)?.parentSystemId;
2240
+ }
2241
+ });
2242
+ function normalizeRoutePath(path) {
2243
+ return path.length > 1 ? path.replace(/\/+$/, "") : path;
2244
+ }
2245
+ const sidebarNodeIds = /* @__PURE__ */ new Map();
2246
+ const sidebarSurfacePaths = /* @__PURE__ */ new Map();
2247
+ const sidebarSurfaces = [];
2248
+ function collectSidebarNodes(nodes, schemaPath) {
2249
+ Object.entries(nodes).forEach(([nodeId, node]) => {
2250
+ const nodePath = [...schemaPath, nodeId];
2251
+ const existingNodePath = sidebarNodeIds.get(nodeId);
2252
+ if (existingNodePath !== void 0) {
2253
+ addIssue(ctx, nodePath, `Sidebar node id "${nodeId}" duplicates another sidebar node`);
2254
+ } else {
2255
+ sidebarNodeIds.set(nodeId, nodePath);
2256
+ }
2257
+ if (node.type === "group") {
2258
+ collectSidebarNodes(node.children, [...nodePath, "children"]);
2259
+ return;
2260
+ }
2261
+ sidebarSurfaces.push({ id: nodeId, node, path: nodePath });
2262
+ const normalizedPath = normalizeRoutePath(node.path);
2263
+ const existingSurfaceId = sidebarSurfacePaths.get(normalizedPath);
2264
+ if (existingSurfaceId !== void 0) {
2265
+ addIssue(
2266
+ ctx,
2267
+ [...nodePath, "path"],
2268
+ `Sidebar surface path "${node.path}" duplicates surface "${existingSurfaceId}"`
2269
+ );
2270
+ } else {
2271
+ sidebarSurfacePaths.set(normalizedPath, nodeId);
2272
+ }
2273
+ node.targets?.systems?.forEach((systemId, systemIndex) => {
2274
+ if (!systemsById.has(systemId)) {
2275
+ addIssue(
2276
+ ctx,
2277
+ [...nodePath, "targets", "systems", systemIndex],
2278
+ `Sidebar surface "${nodeId}" references unknown system "${systemId}"`
2279
+ );
2280
+ }
2281
+ });
2282
+ });
2283
+ }
2284
+ collectSidebarNodes(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]);
2285
+ collectSidebarNodes(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"]);
2286
+ const segmentsById = new Map(Object.entries(model.customers));
2287
+ Object.values(model.offerings).forEach((product) => {
2288
+ product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
2289
+ if (!segmentsById.has(segmentId)) {
2290
+ addIssue(
2291
+ ctx,
2292
+ ["offerings", product.id, "targetSegmentIds", segmentIndex],
2293
+ `Product "${product.id}" references unknown customer segment "${segmentId}"`
2294
+ );
2295
+ }
2296
+ });
2297
+ if (product.deliveryFeatureId !== void 0 && !systemsById.has(product.deliveryFeatureId)) {
2298
+ addIssue(
2299
+ ctx,
2300
+ ["offerings", product.id, "deliveryFeatureId"],
2301
+ `Product "${product.id}" references unknown delivery system "${product.deliveryFeatureId}"`
2302
+ );
2303
+ }
2304
+ });
2305
+ Object.values(model.goals).forEach((objective) => {
2306
+ if (objective.periodEnd <= objective.periodStart) {
2307
+ addIssue(
2308
+ ctx,
2309
+ ["goals", objective.id, "periodEnd"],
2310
+ `Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
2311
+ );
2312
+ }
2313
+ });
2314
+ const goalsById = new Map(Object.entries(model.goals));
2315
+ const knowledgeById = new Map(Object.entries(model.knowledge));
2316
+ const actionsById = new Map(Object.entries(model.actions));
2317
+ const entitiesById = new Map(Object.entries(model.entities));
2318
+ const policiesById = new Map(Object.entries(model.policies));
2319
+ sidebarSurfaces.forEach(({ id, node, path }) => {
2320
+ node.targets?.entities?.forEach((entityId, entityIndex) => {
2321
+ if (!entitiesById.has(entityId)) {
2322
+ addIssue(
2323
+ ctx,
2324
+ [...path, "targets", "entities", entityIndex],
2325
+ `Sidebar surface "${id}" references unknown entity "${entityId}"`
2326
+ );
2327
+ }
2328
+ });
2329
+ node.targets?.actions?.forEach((actionId, actionIndex) => {
2330
+ if (!actionsById.has(actionId)) {
2331
+ addIssue(
2332
+ ctx,
2333
+ [...path, "targets", "actions", actionIndex],
2334
+ `Sidebar surface "${id}" references unknown action "${actionId}"`
2335
+ );
2336
+ }
2337
+ });
2338
+ });
2339
+ Object.values(model.entities).forEach((entity) => {
2340
+ if (!systemsById.has(entity.ownedBySystemId)) {
2341
+ addIssue(
2342
+ ctx,
2343
+ ["entities", entity.id, "ownedBySystemId"],
2344
+ `Entity "${entity.id}" references unknown ownedBySystemId "${entity.ownedBySystemId}"`
2345
+ );
2346
+ }
2347
+ entity.links?.forEach((link, linkIndex) => {
2348
+ if (!entitiesById.has(link.toEntity)) {
2349
+ addIssue(
2350
+ ctx,
2351
+ ["entities", entity.id, "links", linkIndex, "toEntity"],
2352
+ `Entity "${entity.id}" links to unknown entity "${link.toEntity}"`
2353
+ );
2354
+ }
2355
+ });
2356
+ });
2357
+ const rolesById = new Map(Object.entries(model.roles));
2358
+ Object.values(model.roles).forEach((role) => {
2359
+ if (role.reportsToId !== void 0 && !rolesById.has(role.reportsToId)) {
2360
+ addIssue(
2361
+ ctx,
2362
+ ["roles", role.id, "reportsToId"],
2363
+ `Role "${role.id}" references unknown reportsToId "${role.reportsToId}"`
2364
+ );
2365
+ }
2366
+ });
2367
+ Object.values(model.roles).forEach((role) => {
2368
+ const visited = /* @__PURE__ */ new Set();
2369
+ let currentReportsToId = role.reportsToId;
2370
+ while (currentReportsToId !== void 0) {
2371
+ if (currentReportsToId === role.id || visited.has(currentReportsToId)) {
2372
+ addIssue(ctx, ["roles", role.id, "reportsToId"], `Role "${role.id}" has a reportsToId cycle`);
2373
+ return;
2374
+ }
2375
+ visited.add(currentReportsToId);
2376
+ currentReportsToId = rolesById.get(currentReportsToId)?.reportsToId;
2377
+ }
2378
+ });
2379
+ Object.values(model.roles).forEach((role) => {
2380
+ role.responsibleFor?.forEach((systemId, systemIndex) => {
2381
+ if (!systemsById.has(systemId)) {
2382
+ addIssue(
2383
+ ctx,
2384
+ ["roles", role.id, "responsibleFor", systemIndex],
2385
+ `Role "${role.id}" references unknown responsibleFor system "${systemId}"`
2386
+ );
2387
+ }
2388
+ });
2389
+ });
2390
+ allSystems.forEach(({ schemaPath, system }) => {
2391
+ if (system.responsibleRoleId !== void 0 && !rolesById.has(system.responsibleRoleId)) {
2392
+ addIssue(
2393
+ ctx,
2394
+ [...schemaPath, "responsibleRoleId"],
2395
+ `System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
2396
+ );
2397
+ }
2398
+ system.governedByKnowledge?.forEach((nodeId, nodeIndex) => {
2399
+ if (!knowledgeById.has(nodeId)) {
2400
+ addIssue(
2401
+ ctx,
2402
+ [...schemaPath, "governedByKnowledge", nodeIndex],
2403
+ `System "${system.id}" references unknown knowledge node "${nodeId}"`
2404
+ );
2405
+ }
2406
+ });
2407
+ system.drivesGoals?.forEach((goalId, goalIndex) => {
2408
+ if (!goalsById.has(goalId)) {
2409
+ addIssue(
2410
+ ctx,
2411
+ [...schemaPath, "drivesGoals", goalIndex],
2412
+ `System "${system.id}" references unknown goal "${goalId}"`
2413
+ );
2414
+ }
2415
+ });
2416
+ system.actions?.forEach((actionRef, actionIndex) => {
2417
+ if (!actionsById.has(actionRef.actionId)) {
2418
+ addIssue(
2419
+ ctx,
2420
+ [...schemaPath, "actions", actionIndex, "actionId"],
2421
+ `System "${system.id}" references unknown action "${actionRef.actionId}"`
2422
+ );
2423
+ }
2424
+ });
2425
+ system.policies?.forEach((policyId, policyIndex) => {
2426
+ if (!policiesById.has(policyId)) {
2427
+ addIssue(
2428
+ ctx,
2429
+ [...schemaPath, "policies", policyIndex],
2430
+ `System "${system.id}" references unknown policy "${policyId}"`
2431
+ );
2432
+ }
2433
+ });
2434
+ });
2435
+ Object.values(model.actions).forEach((action) => {
2436
+ action.affects?.forEach((entityId, entityIndex) => {
2437
+ if (!entitiesById.has(entityId)) {
2438
+ addIssue(
2439
+ ctx,
2440
+ ["actions", action.id, "affects", entityIndex],
2441
+ `Action "${action.id}" affects unknown entity "${entityId}"`
2442
+ );
2443
+ }
2444
+ });
2445
+ });
2446
+ const resourcesById = new Map(Object.entries(model.resources));
2447
+ sidebarSurfaces.forEach(({ id, node, path }) => {
2448
+ node.targets?.resources?.forEach((resourceId, resourceIndex) => {
2449
+ if (!resourcesById.has(resourceId)) {
2450
+ addIssue(
2451
+ ctx,
2452
+ [...path, "targets", "resources", resourceIndex],
2453
+ `Sidebar surface "${id}" references unknown resource "${resourceId}"`
2454
+ );
2455
+ }
2456
+ });
2457
+ });
2458
+ const stageIds = /* @__PURE__ */ new Set();
2459
+ const actionIds = new Set(Object.keys(model.actions));
2460
+ const offeringsById = new Map(Object.entries(model.offerings));
2461
+ const ontologyCompilation = compileOrganizationOntology(model);
2462
+ const ontologyIndexByKind = {
2463
+ object: ontologyCompilation.ontology.objectTypes,
2464
+ link: ontologyCompilation.ontology.linkTypes,
2465
+ action: ontologyCompilation.ontology.actionTypes,
2466
+ catalog: ontologyCompilation.ontology.catalogTypes,
2467
+ event: ontologyCompilation.ontology.eventTypes,
2468
+ interface: ontologyCompilation.ontology.interfaceTypes,
2469
+ "value-type": ontologyCompilation.ontology.valueTypes,
2470
+ property: ontologyCompilation.ontology.sharedProperties,
2471
+ group: ontologyCompilation.ontology.groups,
2472
+ surface: ontologyCompilation.ontology.surfaces
2473
+ };
2474
+ const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)));
2475
+ function topologyTargetExists(ref) {
2476
+ if (ref.kind === "system") return systemsById.has(ref.id);
2477
+ if (ref.kind === "resource") return resourcesById.has(ref.id);
2478
+ if (ref.kind === "ontology") return ontologyIds.has(ref.id);
2479
+ if (ref.kind === "policy") return policiesById.has(ref.id);
2480
+ if (ref.kind === "role") return rolesById.has(ref.id);
2481
+ return true;
2482
+ }
2483
+ Object.entries(model.topology.relationships).forEach(([relationshipId, relationship]) => {
2484
+ ["from", "to"].forEach((side) => {
2485
+ const ref = relationship[side];
2486
+ if (topologyTargetExists(ref)) return;
2487
+ addIssue(
2488
+ ctx,
2489
+ ["topology", "relationships", relationshipId, side],
2490
+ `Topology relationship "${relationshipId}" ${side} references unknown ${ref.kind} "${ref.id}"`
2491
+ );
2492
+ });
2493
+ });
2494
+ const ontologyReferenceKeyKinds = {
2495
+ valueType: "value-type",
2496
+ catalogType: "catalog",
2497
+ objectType: "object",
2498
+ eventType: "event",
2499
+ actionType: "action",
2500
+ linkType: "link",
2501
+ interfaceType: "interface",
2502
+ propertyType: "property",
2503
+ groupType: "group",
2504
+ surfaceType: "surface",
2505
+ stepCatalog: "catalog"
2506
+ };
2507
+ function validateKnownOntologyReferences(ownerId, value, path, seen = /* @__PURE__ */ new WeakSet()) {
2508
+ if (Array.isArray(value)) {
2509
+ value.forEach((entry, index) => validateKnownOntologyReferences(ownerId, entry, [...path, index], seen));
2510
+ return;
2511
+ }
2512
+ if (!isRecord(value)) return;
2513
+ if (seen.has(value)) return;
2514
+ seen.add(value);
2515
+ Object.entries(value).forEach(([key, entry]) => {
2516
+ const expectedKind = ontologyReferenceKeyKinds[key];
2517
+ if (expectedKind !== void 0) {
2518
+ if (typeof entry !== "string") {
2519
+ addIssue(ctx, [...path, key], `Ontology record "${ownerId}" ${key} must be an ontology ID string`);
2520
+ } else if (ontologyIndexByKind[expectedKind][entry] === void 0) {
2521
+ addIssue(
2522
+ ctx,
2523
+ [...path, key],
2524
+ `Ontology record "${ownerId}" ${key} references unknown ${expectedKind} ontology ID "${entry}"`
2525
+ );
2526
+ }
2527
+ }
2528
+ validateKnownOntologyReferences(ownerId, entry, [...path, key], seen);
2529
+ });
2530
+ }
2531
+ for (const { id, record } of listResolvedOntologyRecords(ontologyCompilation.ontology)) {
2532
+ validateKnownOntologyReferences(id, record, record.origin.path);
2533
+ }
2534
+ Object.values(model.policies).forEach((policy) => {
2535
+ policy.appliesTo.systemIds.forEach((systemId, systemIndex) => {
2536
+ if (!systemsById.has(systemId)) {
2537
+ addIssue(
2538
+ ctx,
2539
+ ["policies", policy.id, "appliesTo", "systemIds", systemIndex],
2540
+ `Policy "${policy.id}" applies to unknown system "${systemId}"`
2541
+ );
2542
+ }
2543
+ });
2544
+ policy.appliesTo.actionIds.forEach((actionId, actionIndex) => {
2545
+ if (!actionsById.has(actionId)) {
2546
+ addIssue(
2547
+ ctx,
2548
+ ["policies", policy.id, "appliesTo", "actionIds", actionIndex],
2549
+ `Policy "${policy.id}" applies to unknown action "${actionId}"`
2550
+ );
2551
+ }
2552
+ });
2553
+ policy.actions.forEach((action, actionIndex) => {
2554
+ if (action.kind === "invoke-action" && !actionsById.has(action.actionId)) {
2555
+ addIssue(
2556
+ ctx,
2557
+ ["policies", policy.id, "actions", actionIndex, "actionId"],
2558
+ `Policy "${policy.id}" invokes unknown action "${action.actionId}"`
2559
+ );
2560
+ }
2561
+ if ((action.kind === "notify-role" || action.kind === "require-approval") && action.roleId !== void 0 && !rolesById.has(action.roleId)) {
2562
+ addIssue(
2563
+ ctx,
2564
+ ["policies", policy.id, "actions", actionIndex, "roleId"],
2565
+ `Policy "${policy.id}" references unknown role "${action.roleId}"`
2566
+ );
2567
+ }
2568
+ });
2569
+ if (policy.trigger.kind === "action-invocation" && !actionsById.has(policy.trigger.actionId)) {
2570
+ addIssue(
2571
+ ctx,
2572
+ ["policies", policy.id, "trigger", "actionId"],
2573
+ `Policy "${policy.id}" references unknown trigger action "${policy.trigger.actionId}"`
2574
+ );
2575
+ }
2576
+ });
2577
+ function knowledgeTargetExists(kind, id) {
2578
+ if (kind === "system") return systemsById.has(id);
2579
+ if (kind === "resource") return resourcesById.has(id);
2580
+ if (kind === "knowledge") return knowledgeById.has(id);
2581
+ if (kind === "stage") return stageIds.has(id);
2582
+ if (kind === "action") return actionIds.has(id);
2583
+ if (kind === "role") return rolesById.has(id);
2584
+ if (kind === "goal") return goalsById.has(id);
2585
+ if (kind === "customer-segment") return segmentsById.has(id);
2586
+ if (kind === "offering") return offeringsById.has(id);
2587
+ if (kind === "ontology") return ontologyIds.has(id);
2588
+ return false;
2589
+ }
2590
+ Object.entries(model.knowledge).forEach(([nodeId, node]) => {
2591
+ node.links.forEach((link, linkIndex) => {
2592
+ if (!knowledgeTargetExists(link.target.kind, link.target.id)) {
2593
+ addIssue(
2594
+ ctx,
2595
+ ["knowledge", nodeId, "links", linkIndex, "target"],
2596
+ `Knowledge node "${node.id}" references unknown ${link.target.kind} target "${link.target.id}"`
2597
+ );
2598
+ }
2599
+ if (!isKnowledgeKindCompatibleWithTarget(node.kind, link.target.kind)) {
2600
+ addIssue(
2601
+ ctx,
2602
+ ["knowledge", nodeId, "links", linkIndex, "target", "kind"],
2603
+ `Knowledge node "${node.id}" kind "${node.kind}" cannot govern ${link.target.kind} targets`
2604
+ );
2605
+ }
2606
+ });
2607
+ });
2608
+ Object.values(model.resources).forEach((resource) => {
2609
+ if (!systemsById.has(resource.systemPath)) {
2610
+ addIssue(
2611
+ ctx,
2612
+ ["resources", resource.id, "systemPath"],
2613
+ `Resource "${resource.id}" references unknown system path "${resource.systemPath}"`
2614
+ );
2615
+ }
2616
+ if (resource.ownerRoleId !== void 0 && !rolesById.has(resource.ownerRoleId)) {
2617
+ addIssue(
2618
+ ctx,
2619
+ ["resources", resource.id, "ownerRoleId"],
2620
+ `Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
2621
+ );
2622
+ }
2623
+ if (resource.kind === "agent" && resource.actsAsRoleId !== void 0 && !rolesById.has(resource.actsAsRoleId)) {
2624
+ addIssue(
2625
+ ctx,
2626
+ ["resources", resource.id, "actsAsRoleId"],
2627
+ `Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
2628
+ );
2629
+ }
2630
+ });
2631
+ function validateResourceOntologyBinding(resourceId, bindingKey, expectedKind, ids) {
2632
+ const ontologyIds2 = ids === void 0 ? [] : Array.isArray(ids) ? ids : [ids];
2633
+ ontologyIds2.forEach((ontologyId, ontologyIndex) => {
2634
+ if (ontologyIndexByKind[expectedKind][ontologyId] === void 0) {
2635
+ addIssue(
2636
+ ctx,
2637
+ [
2638
+ "resources",
2639
+ resourceId,
2640
+ "ontology",
2641
+ bindingKey,
2642
+ ...Array.isArray(ids) ? [ontologyIndex] : []
2643
+ ],
2644
+ `Resource "${resourceId}" ontology binding "${bindingKey}" references unknown ${expectedKind} ontology ID "${ontologyId}"`
2645
+ );
2646
+ }
2647
+ });
2648
+ }
2649
+ Object.values(model.resources).forEach((resource) => {
2650
+ const binding = resource.ontology;
2651
+ if (binding === void 0) return;
2652
+ validateResourceOntologyBinding(resource.id, "actions", "action", binding.actions);
2653
+ validateResourceOntologyBinding(resource.id, "primaryAction", "action", binding.primaryAction);
2654
+ validateResourceOntologyBinding(resource.id, "reads", "object", binding.reads);
2655
+ validateResourceOntologyBinding(resource.id, "writes", "object", binding.writes);
2656
+ validateResourceOntologyBinding(resource.id, "usesCatalogs", "catalog", binding.usesCatalogs);
2657
+ validateResourceOntologyBinding(resource.id, "emits", "event", binding.emits);
2658
+ });
2659
+ Object.values(model.roles).forEach((role) => {
2660
+ if (role.heldBy === void 0) return;
2661
+ asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
2662
+ if (holder.kind !== "agent") return;
2663
+ const resource = resourcesById.get(holder.agentId);
2664
+ if (resource === void 0) {
2665
+ addIssue(
2666
+ ctx,
2667
+ ["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
2668
+ `Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
2669
+ );
2670
+ return;
2671
+ }
2672
+ if (resource.kind !== "agent") {
2673
+ addIssue(
2674
+ ctx,
2675
+ ["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
2676
+ `Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
2677
+ );
2678
+ }
2679
+ });
2680
+ });
2681
+ Object.entries(model.knowledge).forEach(([nodeId, node]) => {
2682
+ node.ownerIds.forEach((roleId, ownerIndex) => {
2683
+ if (!rolesById.has(roleId)) {
2684
+ addIssue(
2685
+ ctx,
2686
+ ["knowledge", nodeId, "ownerIds", ownerIndex],
2687
+ `Knowledge node "${node.id}" references unknown owner role "${roleId}"`
2688
+ );
2689
+ }
2690
+ });
2691
+ });
2692
+ function validateSystemContent(system, systemPath) {
2693
+ const childSystems = system.systems ?? system.subsystems;
2694
+ const childKey = system.systems !== void 0 ? "systems" : "subsystems";
2695
+ const content = system.content;
2696
+ if (content === void 0 || Object.keys(content).length === 0) {
2697
+ if (childSystems !== void 0) {
2698
+ Object.entries(childSystems).forEach(([childLocalId, child]) => {
2699
+ validateSystemContent(child, [...systemPath, childKey, childLocalId]);
2700
+ });
2701
+ }
2702
+ return;
2703
+ }
2704
+ Object.entries(content).forEach(([localId, node]) => {
2705
+ if (node.parentContentId !== void 0 && !(node.parentContentId in content)) {
2706
+ addIssue(
2707
+ ctx,
2708
+ [...systemPath, "content", localId, "parentContentId"],
2709
+ `Content node "${localId}" parentContentId "${node.parentContentId}" does not resolve within the same system`
2710
+ );
2711
+ }
2712
+ });
2713
+ Object.entries(content).forEach(([localId, node]) => {
2714
+ const visited = /* @__PURE__ */ new Set();
2715
+ let currentId = node.parentContentId;
2716
+ while (currentId !== void 0) {
2717
+ if (currentId === localId || visited.has(currentId)) {
2718
+ addIssue(
2719
+ ctx,
2720
+ [...systemPath, "content", localId, "parentContentId"],
2721
+ `Content node "${localId}" has a parentContentId cycle`
2722
+ );
2723
+ break;
2724
+ }
2725
+ visited.add(currentId);
2726
+ currentId = content[currentId]?.parentContentId;
2727
+ }
2728
+ });
2729
+ Object.entries(content).forEach(([localId, node]) => {
2730
+ const childDef = lookupContentType(node.kind, node.type);
2731
+ if (childDef !== void 0 && node.data !== void 0) {
2732
+ const result = childDef.payloadSchema.safeParse(node.data);
2733
+ if (!result.success) {
2734
+ addIssue(
2735
+ ctx,
2736
+ [...systemPath, "content", localId, "data"],
2737
+ `Content node "${localId}" (${node.kind}:${node.type}) data failed payload validation: ${result.error.message}`
2738
+ );
2739
+ }
2740
+ }
2741
+ if (node.parentContentId !== void 0 && childDef !== void 0) {
2742
+ const parentNode = content[node.parentContentId];
2743
+ if (parentNode !== void 0) {
2744
+ const parentDef = lookupContentType(parentNode.kind, parentNode.type);
2745
+ if (parentDef !== void 0 && childDef.kind !== parentDef.kind) {
2746
+ addIssue(
2747
+ ctx,
2748
+ [...systemPath, "content", localId, "parentContentId"],
2749
+ `Content node "${localId}" kind "${childDef.kind}" cannot parent under "${node.parentContentId}" kind "${parentDef.kind}": parentContentId must be same-meta-kind (per L19)`
2750
+ );
2751
+ }
2752
+ }
2753
+ }
2754
+ });
2755
+ if (childSystems !== void 0) {
2756
+ Object.entries(childSystems).forEach(([childLocalId, child]) => {
2757
+ validateSystemContent(child, [...systemPath, childKey, childLocalId]);
2758
+ });
2759
+ }
2760
+ }
2761
+ Object.entries(model.systems).forEach(([systemKey, system]) => {
2762
+ validateSystemContent(system, ["systems", systemKey]);
2763
+ });
2764
+ for (const diagnostic of ontologyCompilation.diagnostics) {
2765
+ addIssue(ctx, diagnostic.path, diagnostic.message);
2766
+ }
2767
+ });
492
2768
 
493
2769
  // ../core/src/platform/registry/reserved.ts
494
2770
  var RESERVED_RESOURCE_IDS = /* @__PURE__ */ new Set(["command-center-assistant"]);
@@ -498,14 +2774,18 @@ function isReservedResourceId(resourceId) {
498
2774
  }
499
2775
 
500
2776
  // ../core/src/organization-model/helpers.ts
2777
+ function childSystemsOf2(system) {
2778
+ return system.systems ?? system.subsystems ?? {};
2779
+ }
501
2780
  function listAllSystems(model) {
502
2781
  const results = [];
503
2782
  function walk(map, prefix) {
504
2783
  for (const [localId, system] of Object.entries(map)) {
505
2784
  const fullPath = prefix ? `${prefix}.${localId}` : localId;
506
2785
  results.push({ path: fullPath, system });
507
- if (system.subsystems) {
508
- walk(system.subsystems, fullPath);
2786
+ const childSystems = childSystemsOf2(system);
2787
+ if (Object.keys(childSystems).length > 0) {
2788
+ walk(childSystems, fullPath);
509
2789
  }
510
2790
  }
511
2791
  }
@@ -817,6 +3097,119 @@ function getRuntimeResources(resources) {
817
3097
  }))
818
3098
  ];
819
3099
  }
3100
+ function hasOntologySources(organizationModel) {
3101
+ return organizationModel.ontology !== void 0 || organizationModel.entities !== void 0 || organizationModel.actions !== void 0 || Object.values(organizationModel.systems ?? {}).some(systemHasOntologySource);
3102
+ }
3103
+ function systemHasOntologySource(system) {
3104
+ if (system.ontology !== void 0 || system.content !== void 0 && Object.keys(system.content).length > 0) return true;
3105
+ return Object.values(system.systems ?? system.subsystems ?? {}).some(systemHasOntologySource);
3106
+ }
3107
+ function ontologyIndexForKind(index, kind) {
3108
+ switch (kind) {
3109
+ case "object":
3110
+ return index.objectTypes;
3111
+ case "link":
3112
+ return index.linkTypes;
3113
+ case "action":
3114
+ return index.actionTypes;
3115
+ case "catalog":
3116
+ return index.catalogTypes;
3117
+ case "event":
3118
+ return index.eventTypes;
3119
+ case "interface":
3120
+ return index.interfaceTypes;
3121
+ case "value-type":
3122
+ return index.valueTypes;
3123
+ case "property":
3124
+ return index.sharedProperties;
3125
+ case "group":
3126
+ return index.groups;
3127
+ case "surface":
3128
+ return index.surfaces;
3129
+ }
3130
+ }
3131
+ function sameJson(left, right) {
3132
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
3133
+ }
3134
+ function addOntologyBindingIssues(issues, orgName, resource, ontologyIndex) {
3135
+ const binding = resource.ontology;
3136
+ if (binding === void 0) return;
3137
+ if ((resource.kind === "workflow" || resource.kind === "agent") && (binding.actions?.length ?? 0) === 0) {
3138
+ addGovernanceIssue(
3139
+ issues,
3140
+ "missing-ontology-actions",
3141
+ orgName,
3142
+ resource.id,
3143
+ `[${orgName}] Resource '${resource.id}' declares ontology bindings but no ontology actions.`
3144
+ );
3145
+ }
3146
+ if (binding.primaryAction !== void 0 && !binding.actions?.includes(binding.primaryAction)) {
3147
+ addGovernanceIssue(
3148
+ issues,
3149
+ "primary-action-mismatch",
3150
+ orgName,
3151
+ resource.id,
3152
+ `[${orgName}] Resource '${resource.id}' primaryAction '${binding.primaryAction}' must be included in ontology.actions.`
3153
+ );
3154
+ }
3155
+ if (ontologyIndex === void 0) return;
3156
+ const validateRefs = (bindingKey, expectedKind, refs) => {
3157
+ const values = refs === void 0 ? [] : Array.isArray(refs) ? refs : [refs];
3158
+ const index = ontologyIndexForKind(ontologyIndex, expectedKind);
3159
+ for (const ref of values) {
3160
+ if (index[ref] !== void 0) continue;
3161
+ addGovernanceIssue(
3162
+ issues,
3163
+ "ontology-reference-missing",
3164
+ orgName,
3165
+ resource.id,
3166
+ `[${orgName}] Resource '${resource.id}' ontology.${bindingKey} references missing ${expectedKind} ontology record '${ref}'.`
3167
+ );
3168
+ }
3169
+ };
3170
+ validateRefs("actions", "action", binding.actions);
3171
+ validateRefs("primaryAction", "action", binding.primaryAction);
3172
+ validateRefs("reads", "object", binding.reads);
3173
+ validateRefs("writes", "object", binding.writes);
3174
+ validateRefs("usesCatalogs", "catalog", binding.usesCatalogs);
3175
+ validateRefs("emits", "event", binding.emits);
3176
+ }
3177
+ function addTopologyIssues(issues, orgName, deployment, organizationModel, systemsById, omResourcesById, ontologyIndex) {
3178
+ const relationships = organizationModel.topology?.relationships;
3179
+ if (relationships === void 0) return;
3180
+ const rolesById = new Set(Object.keys(organizationModel.roles ?? {}));
3181
+ const policiesById = new Set(Object.keys(organizationModel.policies ?? {}));
3182
+ const triggerIds = new Set(deployment.triggers?.map((trigger) => trigger.resourceId) ?? []);
3183
+ const humanCheckpointIds = new Set(deployment.humanCheckpoints?.map((checkpoint) => checkpoint.resourceId) ?? []);
3184
+ const externalResourceIds = new Set(deployment.externalResources?.map((external) => external.resourceId) ?? []);
3185
+ const topologyRefExists = (ref) => {
3186
+ if (ref.kind === "system") return systemsById.has(ref.id);
3187
+ if (ref.kind === "resource") return omResourcesById.has(ref.id);
3188
+ if (ref.kind === "policy") return policiesById.has(ref.id);
3189
+ if (ref.kind === "role") return rolesById.has(ref.id);
3190
+ if (ref.kind === "trigger") return triggerIds.has(ref.id);
3191
+ if (ref.kind === "humanCheckpoint") return humanCheckpointIds.has(ref.id);
3192
+ if (ref.kind === "externalResource") return externalResourceIds.has(ref.id);
3193
+ if (ref.kind === "ontology") {
3194
+ if (ontologyIndex === void 0) return true;
3195
+ return Object.values(ontologyIndex).some((records) => records[ref.id] !== void 0);
3196
+ }
3197
+ return false;
3198
+ };
3199
+ for (const [relationshipId, relationship] of Object.entries(relationships)) {
3200
+ ["from", "to"].forEach((side) => {
3201
+ const ref = relationship[side];
3202
+ if (topologyRefExists(ref)) return;
3203
+ addGovernanceIssue(
3204
+ issues,
3205
+ "topology-reference-missing",
3206
+ orgName,
3207
+ ref.id,
3208
+ `[${orgName}] Topology relationship '${relationshipId}' ${side} references missing ${ref.kind} '${ref.id}'.`
3209
+ );
3210
+ });
3211
+ }
3212
+ }
820
3213
  function validateResourceGovernance(orgName, deployment, organizationModel = deployment.organizationModel, options = {}) {
821
3214
  const mode = getResourceValidatorMode(options.mode);
822
3215
  const omResourcesMap = organizationModel?.resources;
@@ -832,6 +3225,17 @@ function validateResourceGovernance(orgName, deployment, organizationModel = dep
832
3225
  const omResourcesById = new Map(activeOmResources.map((resource) => [resource.id, resource]));
833
3226
  const runtimeResources = getRuntimeResources(deployment);
834
3227
  const runtimeResourcesById = new Map(runtimeResources.map((resource) => [resource.resourceId, resource]));
3228
+ const ontologyCompilation = hasOntologySources(organizationModel) ? compileOrganizationOntology(organizationModel) : void 0;
3229
+ const ontologyIndex = ontologyCompilation?.ontology;
3230
+ for (const diagnostic of ontologyCompilation?.diagnostics ?? []) {
3231
+ addGovernanceIssue(
3232
+ issues,
3233
+ "ontology-reference-missing",
3234
+ orgName,
3235
+ diagnostic.id,
3236
+ `[${orgName}] ${diagnostic.message}`
3237
+ );
3238
+ }
835
3239
  for (const resource of activeOmResources) {
836
3240
  if (!systemsById.has(resource.systemPath)) {
837
3241
  addGovernanceIssue(
@@ -871,6 +3275,16 @@ function validateResourceGovernance(orgName, deployment, organizationModel = dep
871
3275
  `[${orgName}] Resource '${resource.id}' system mismatch: code descriptor has '${runtimeResource.descriptor.systemPath}', OM has '${resource.systemPath}'.`
872
3276
  );
873
3277
  }
3278
+ if (runtimeResource.descriptor && !sameJson(runtimeResource.descriptor.ontology, resource.ontology)) {
3279
+ addGovernanceIssue(
3280
+ issues,
3281
+ "descriptor-mismatch",
3282
+ orgName,
3283
+ resource.id,
3284
+ `[${orgName}] Resource '${resource.id}' ontology descriptor mismatch between code and OM.`
3285
+ );
3286
+ }
3287
+ addOntologyBindingIssues(issues, orgName, resource, ontologyIndex);
874
3288
  }
875
3289
  for (const runtimeResource of runtimeResources) {
876
3290
  const omResource = omResourcesById.get(runtimeResource.resourceId);
@@ -912,6 +3326,7 @@ function validateResourceGovernance(orgName, deployment, organizationModel = dep
912
3326
  );
913
3327
  }
914
3328
  }
3329
+ addTopologyIssues(issues, orgName, deployment, organizationModel, systemsById, omResourcesById, ontologyIndex);
915
3330
  emitGovernanceIssues(issues, mode, options.onWarning);
916
3331
  return {
917
3332
  valid: issues.length === 0,
@@ -4292,6 +6707,17 @@ var ResourceRegistry = class {
4292
6707
  return cache.commandView;
4293
6708
  }
4294
6709
  };
6710
+
6711
+ // ../core/src/platform/registry/types.ts
6712
+ function bindResourceDescriptor(definition) {
6713
+ const { resource, ...rest } = definition;
6714
+ return {
6715
+ ...rest,
6716
+ resource,
6717
+ resourceId: resource.id,
6718
+ type: resource.kind
6719
+ };
6720
+ }
4295
6721
  DisplayMetadataSchema.extend({
4296
6722
  id: ModelIdSchema,
4297
6723
  order: z.number().min(0)
@@ -4428,7 +6854,7 @@ var DTC_RECORD_COLUMNS = {
4428
6854
  ]
4429
6855
  }
4430
6856
  };
4431
- var ACTION_REGISTRY = Object.values(LEAD_GEN_ACTION_ENTRIES);
6857
+ Object.values(LEAD_GEN_ACTION_ENTRIES);
4432
6858
  var PROSPECTING_STEPS = {
4433
6859
  localServices: {
4434
6860
  sourceCompanies: {
@@ -4846,6 +7272,931 @@ var CRM_PIPELINE_DEFINITION = {
4846
7272
  ]
4847
7273
  };
4848
7274
 
7275
+ // ../core/src/organization-model/defaults.ts
7276
+ var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
7277
+ var DEFAULT_ORGANIZATION_MODEL_ENTITIES2 = DEFAULT_ORGANIZATION_MODEL_ENTITIES;
7278
+ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
7279
+ sidebar: {
7280
+ primary: {
7281
+ dashboard: {
7282
+ type: "surface",
7283
+ label: "Dashboard",
7284
+ path: "/",
7285
+ surfaceType: "dashboard",
7286
+ icon: "dashboard",
7287
+ order: 10,
7288
+ targets: { systems: ["dashboard"] }
7289
+ },
7290
+ business: {
7291
+ type: "group",
7292
+ label: "Business",
7293
+ icon: "business",
7294
+ order: 20,
7295
+ children: {
7296
+ sales: {
7297
+ type: "surface",
7298
+ label: "Sales",
7299
+ path: "/sales",
7300
+ surfaceType: "page",
7301
+ icon: "sales",
7302
+ order: 10,
7303
+ targets: { systems: ["sales"] }
7304
+ },
7305
+ clients: {
7306
+ type: "surface",
7307
+ label: "Clients",
7308
+ path: "/clients",
7309
+ surfaceType: "list",
7310
+ icon: "projects",
7311
+ order: 20,
7312
+ targets: { systems: ["clients"] }
7313
+ },
7314
+ projects: {
7315
+ type: "surface",
7316
+ label: "Projects",
7317
+ path: "/projects",
7318
+ surfaceType: "page",
7319
+ icon: "projects",
7320
+ order: 30,
7321
+ targets: { systems: ["projects"] }
7322
+ }
7323
+ }
7324
+ },
7325
+ operations: {
7326
+ type: "group",
7327
+ label: "Operations",
7328
+ icon: "operations",
7329
+ order: 30,
7330
+ children: {
7331
+ "operations-overview": {
7332
+ type: "surface",
7333
+ label: "Overview",
7334
+ path: "/operations",
7335
+ surfaceType: "page",
7336
+ order: 10,
7337
+ targets: { systems: ["operations.overview"] }
7338
+ },
7339
+ "operations-systems": {
7340
+ type: "surface",
7341
+ label: "Systems",
7342
+ path: "/operations/systems",
7343
+ surfaceType: "page",
7344
+ order: 20,
7345
+ targets: { systems: ["operations"] }
7346
+ },
7347
+ "operations-resources": {
7348
+ type: "surface",
7349
+ label: "Resources",
7350
+ path: "/operations/resources",
7351
+ surfaceType: "list",
7352
+ order: 30,
7353
+ targets: { systems: ["operations.resources"] }
7354
+ },
7355
+ "operations-command-queue": {
7356
+ type: "surface",
7357
+ label: "Command Queue",
7358
+ path: "/operations/command-queue",
7359
+ surfaceType: "list",
7360
+ order: 40,
7361
+ targets: { systems: ["operations.command-queue"] }
7362
+ },
7363
+ "operations-task-scheduler": {
7364
+ type: "surface",
7365
+ label: "Task Scheduler",
7366
+ path: "/operations/task-scheduler",
7367
+ surfaceType: "list",
7368
+ order: 50,
7369
+ targets: { systems: ["operations.task-scheduler"] }
7370
+ }
7371
+ }
7372
+ },
7373
+ monitoring: {
7374
+ type: "group",
7375
+ label: "Monitoring",
7376
+ icon: "monitoring",
7377
+ order: 40,
7378
+ children: {
7379
+ "monitoring-overview": {
7380
+ type: "surface",
7381
+ label: "Overview",
7382
+ path: "/monitoring",
7383
+ surfaceType: "page",
7384
+ order: 10,
7385
+ targets: { systems: ["monitoring"] }
7386
+ },
7387
+ "monitoring-calendar": {
7388
+ type: "surface",
7389
+ label: "Calendar",
7390
+ path: "/monitoring/calendar",
7391
+ surfaceType: "page",
7392
+ order: 20,
7393
+ targets: { systems: ["monitoring.calendar"] }
7394
+ },
7395
+ "monitoring-activity-log": {
7396
+ type: "surface",
7397
+ label: "Activity Log",
7398
+ path: "/monitoring/activity-log",
7399
+ surfaceType: "list",
7400
+ order: 30,
7401
+ targets: { systems: ["monitoring.activity-log"] }
7402
+ },
7403
+ "monitoring-execution-logs": {
7404
+ type: "surface",
7405
+ label: "Execution Logs",
7406
+ path: "/monitoring/execution-logs",
7407
+ surfaceType: "list",
7408
+ order: 40,
7409
+ targets: { systems: ["monitoring.execution-logs"] }
7410
+ },
7411
+ "monitoring-execution-health": {
7412
+ type: "surface",
7413
+ label: "Execution Health",
7414
+ path: "/monitoring/execution-health",
7415
+ surfaceType: "dashboard",
7416
+ order: 50,
7417
+ targets: { systems: ["monitoring.execution-health"] }
7418
+ },
7419
+ "monitoring-notifications": {
7420
+ type: "surface",
7421
+ label: "Notifications",
7422
+ path: "/monitoring/notifications",
7423
+ surfaceType: "list",
7424
+ order: 60,
7425
+ targets: { systems: ["monitoring.notifications"] }
7426
+ },
7427
+ "monitoring-requests": {
7428
+ type: "surface",
7429
+ label: "Requests",
7430
+ path: "/monitoring/requests",
7431
+ surfaceType: "list",
7432
+ order: 70,
7433
+ targets: { systems: ["monitoring.submitted-requests"] }
7434
+ }
7435
+ }
7436
+ },
7437
+ knowledge: {
7438
+ type: "surface",
7439
+ label: "Knowledge Base",
7440
+ path: "/knowledge",
7441
+ surfaceType: "page",
7442
+ icon: "knowledge",
7443
+ order: 50
7444
+ }
7445
+ },
7446
+ bottom: {
7447
+ settings: {
7448
+ type: "group",
7449
+ label: "Settings",
7450
+ icon: "settings",
7451
+ order: 10,
7452
+ children: {
7453
+ "settings-account": {
7454
+ type: "surface",
7455
+ label: "Account",
7456
+ path: "/settings/account",
7457
+ surfaceType: "settings",
7458
+ order: 10,
7459
+ targets: { systems: ["settings.account"] }
7460
+ },
7461
+ "settings-appearance": {
7462
+ type: "surface",
7463
+ label: "Appearance",
7464
+ path: "/settings/appearance",
7465
+ surfaceType: "settings",
7466
+ order: 20,
7467
+ targets: { systems: ["settings.appearance"] }
7468
+ },
7469
+ "settings-roles": {
7470
+ type: "surface",
7471
+ label: "My Roles",
7472
+ path: "/settings/roles",
7473
+ surfaceType: "settings",
7474
+ order: 30,
7475
+ targets: { systems: ["settings.roles"] }
7476
+ },
7477
+ "settings-organization": {
7478
+ type: "surface",
7479
+ label: "Organization",
7480
+ path: "/settings/organization",
7481
+ surfaceType: "settings",
7482
+ order: 40,
7483
+ targets: { systems: ["settings.organization"] }
7484
+ },
7485
+ "settings-credentials": {
7486
+ type: "surface",
7487
+ label: "Credentials",
7488
+ path: "/settings/credentials",
7489
+ surfaceType: "settings",
7490
+ order: 50,
7491
+ targets: { systems: ["settings.credentials"] }
7492
+ },
7493
+ "settings-api-keys": {
7494
+ type: "surface",
7495
+ label: "API Keys",
7496
+ path: "/settings/api-keys",
7497
+ surfaceType: "settings",
7498
+ order: 60,
7499
+ targets: { systems: ["settings.api-keys"] }
7500
+ },
7501
+ "settings-webhooks": {
7502
+ type: "surface",
7503
+ label: "Webhooks",
7504
+ path: "/settings/webhooks",
7505
+ surfaceType: "settings",
7506
+ order: 70,
7507
+ targets: { systems: ["settings.webhooks"] }
7508
+ },
7509
+ "settings-deployments": {
7510
+ type: "surface",
7511
+ label: "Deployments",
7512
+ path: "/settings/deployments",
7513
+ surfaceType: "settings",
7514
+ order: 80,
7515
+ targets: { systems: ["settings.deployments"] }
7516
+ }
7517
+ }
7518
+ },
7519
+ admin: {
7520
+ type: "group",
7521
+ label: "Admin",
7522
+ icon: "admin",
7523
+ order: 20,
7524
+ children: {
7525
+ "admin-dashboard": {
7526
+ type: "surface",
7527
+ label: "Dashboard",
7528
+ path: "/admin/dashboard",
7529
+ surfaceType: "dashboard",
7530
+ order: 10,
7531
+ targets: { systems: ["admin"] },
7532
+ requiresAdmin: true
7533
+ },
7534
+ "admin-system-health": {
7535
+ type: "surface",
7536
+ label: "System Health",
7537
+ path: "/admin/system-health",
7538
+ surfaceType: "dashboard",
7539
+ order: 20,
7540
+ targets: { systems: ["admin.system-health"] },
7541
+ requiresAdmin: true
7542
+ },
7543
+ "admin-organizations": {
7544
+ type: "surface",
7545
+ label: "Organizations",
7546
+ path: "/admin/organizations",
7547
+ surfaceType: "list",
7548
+ order: 30,
7549
+ targets: { systems: ["admin.organizations"] },
7550
+ requiresAdmin: true
7551
+ },
7552
+ "admin-users": {
7553
+ type: "surface",
7554
+ label: "Users",
7555
+ path: "/admin/users",
7556
+ surfaceType: "list",
7557
+ order: 40,
7558
+ targets: { systems: ["admin.users"] },
7559
+ requiresAdmin: true
7560
+ },
7561
+ "admin-design-showcase": {
7562
+ type: "surface",
7563
+ label: "Design Showcase",
7564
+ path: "/admin/design-showcase",
7565
+ surfaceType: "page",
7566
+ order: 50,
7567
+ targets: { systems: ["admin.design-showcase"] },
7568
+ requiresAdmin: true
7569
+ },
7570
+ "admin-debug": {
7571
+ type: "surface",
7572
+ label: "Debug",
7573
+ path: "/admin/debug",
7574
+ surfaceType: "page",
7575
+ order: 60,
7576
+ targets: { systems: ["admin.debug"] },
7577
+ requiresAdmin: true
7578
+ }
7579
+ }
7580
+ }
7581
+ }
7582
+ }
7583
+ };
7584
+ var DEFAULT_ORGANIZATION_MODEL = {
7585
+ version: 1,
7586
+ domainMetadata: DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA,
7587
+ branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
7588
+ navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
7589
+ identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
7590
+ customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
7591
+ offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
7592
+ roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
7593
+ goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
7594
+ systems: {
7595
+ dashboard: {
7596
+ id: "dashboard",
7597
+ order: 10,
7598
+ label: "Dashboard",
7599
+ enabled: true,
7600
+ lifecycle: "active",
7601
+ path: "/",
7602
+ icon: "dashboard"
7603
+ },
7604
+ platform: {
7605
+ id: "platform",
7606
+ order: 30,
7607
+ label: "Platform",
7608
+ description: "Elevasis platform architecture, capabilities, and implementation patterns",
7609
+ enabled: true,
7610
+ lifecycle: "active",
7611
+ color: "cyan",
7612
+ icon: "platform"
7613
+ },
7614
+ finance: {
7615
+ id: "finance",
7616
+ order: 40,
7617
+ label: "Finance",
7618
+ description: "Finance operations, accounting, billing, reconciliation, and tax prep",
7619
+ enabled: true,
7620
+ lifecycle: "active",
7621
+ color: "green",
7622
+ icon: "finance"
7623
+ },
7624
+ sales: {
7625
+ id: "sales",
7626
+ order: 60,
7627
+ label: "Sales",
7628
+ description: "Revenue workflows and customer acquisition",
7629
+ enabled: true,
7630
+ lifecycle: "active",
7631
+ color: "blue",
7632
+ icon: "sales",
7633
+ path: "/sales"
7634
+ },
7635
+ "sales.crm": {
7636
+ id: "sales.crm",
7637
+ order: 70,
7638
+ label: "CRM",
7639
+ description: "Relationship pipeline and deal management",
7640
+ enabled: true,
7641
+ lifecycle: "active",
7642
+ actions: Object.values(CRM_ACTION_ENTRIES).map((action) => ({
7643
+ actionId: action.id,
7644
+ intent: "exposes"
7645
+ })),
7646
+ color: "blue",
7647
+ icon: "crm",
7648
+ path: "/crm"
7649
+ },
7650
+ "sales.lead-gen": {
7651
+ id: "sales.lead-gen",
7652
+ order: 80,
7653
+ label: "Lead Gen",
7654
+ description: "Prospecting, qualification, and outreach preparation",
7655
+ enabled: true,
7656
+ lifecycle: "active",
7657
+ actions: Object.values(LEAD_GEN_ACTION_ENTRIES).map((action) => ({
7658
+ actionId: action.id,
7659
+ intent: "exposes"
7660
+ })),
7661
+ color: "cyan",
7662
+ icon: "lead-gen",
7663
+ path: "/lead-gen"
7664
+ },
7665
+ projects: {
7666
+ id: "projects",
7667
+ order: 90,
7668
+ label: "Projects",
7669
+ description: "Projects, milestones, and client work execution",
7670
+ enabled: true,
7671
+ lifecycle: "active",
7672
+ color: "orange",
7673
+ icon: "projects",
7674
+ path: "/projects"
7675
+ },
7676
+ clients: {
7677
+ id: "clients",
7678
+ order: 100,
7679
+ label: "Clients",
7680
+ description: "Client relationships, accounts, and business context",
7681
+ enabled: true,
7682
+ lifecycle: "active",
7683
+ color: "orange",
7684
+ icon: "projects",
7685
+ path: "/clients"
7686
+ },
7687
+ operations: {
7688
+ id: "operations",
7689
+ order: 110,
7690
+ label: "Operations",
7691
+ description: "Operational resources, topology, and orchestration visibility",
7692
+ enabled: true,
7693
+ lifecycle: "active",
7694
+ color: "violet",
7695
+ icon: "operations"
7696
+ },
7697
+ "knowledge.command-view": {
7698
+ id: "knowledge.command-view",
7699
+ order: 120,
7700
+ label: "Command View",
7701
+ enabled: true,
7702
+ lifecycle: "active",
7703
+ path: "/knowledge/command-view",
7704
+ devOnly: true
7705
+ },
7706
+ "operations.overview": {
7707
+ id: "operations.overview",
7708
+ order: 130,
7709
+ label: "Overview",
7710
+ enabled: true,
7711
+ lifecycle: "active",
7712
+ path: "/operations"
7713
+ },
7714
+ "operations.resources": {
7715
+ id: "operations.resources",
7716
+ order: 140,
7717
+ label: "Resources",
7718
+ enabled: true,
7719
+ lifecycle: "active",
7720
+ path: "/operations/resources"
7721
+ },
7722
+ "operations.command-queue": {
7723
+ id: "operations.command-queue",
7724
+ order: 150,
7725
+ label: "Command Queue",
7726
+ enabled: true,
7727
+ lifecycle: "active",
7728
+ path: "/operations/command-queue"
7729
+ },
7730
+ "operations.sessions": {
7731
+ id: "operations.sessions",
7732
+ order: 160,
7733
+ label: "Sessions",
7734
+ enabled: false,
7735
+ lifecycle: "deprecated",
7736
+ path: "/operations/sessions"
7737
+ },
7738
+ "operations.task-scheduler": {
7739
+ id: "operations.task-scheduler",
7740
+ order: 170,
7741
+ label: "Task Scheduler",
7742
+ enabled: true,
7743
+ lifecycle: "active",
7744
+ path: "/operations/task-scheduler"
7745
+ },
7746
+ monitoring: {
7747
+ id: "monitoring",
7748
+ order: 180,
7749
+ label: "Monitoring",
7750
+ enabled: true,
7751
+ lifecycle: "active"
7752
+ },
7753
+ "monitoring.calendar": {
7754
+ id: "monitoring.calendar",
7755
+ order: 190,
7756
+ label: "Calendar",
7757
+ description: "Google Calendar events and agenda views",
7758
+ enabled: true,
7759
+ lifecycle: "active",
7760
+ path: "/monitoring/calendar",
7761
+ icon: "calendar"
7762
+ },
7763
+ "monitoring.activity-log": {
7764
+ id: "monitoring.activity-log",
7765
+ order: 200,
7766
+ label: "Activity Log",
7767
+ enabled: true,
7768
+ lifecycle: "active",
7769
+ path: "/monitoring/activity-log"
7770
+ },
7771
+ "monitoring.execution-logs": {
7772
+ id: "monitoring.execution-logs",
7773
+ order: 210,
7774
+ label: "Execution Logs",
7775
+ enabled: true,
7776
+ lifecycle: "active",
7777
+ path: "/monitoring/execution-logs"
7778
+ },
7779
+ "monitoring.execution-health": {
7780
+ id: "monitoring.execution-health",
7781
+ order: 220,
7782
+ label: "Execution Health",
7783
+ enabled: true,
7784
+ lifecycle: "active",
7785
+ path: "/monitoring/execution-health"
7786
+ },
7787
+ "monitoring.cost-analytics": {
7788
+ id: "monitoring.cost-analytics",
7789
+ order: 230,
7790
+ label: "Cost Analytics",
7791
+ enabled: false,
7792
+ lifecycle: "deprecated",
7793
+ path: "/monitoring/cost-analytics"
7794
+ },
7795
+ "monitoring.notifications": {
7796
+ id: "monitoring.notifications",
7797
+ order: 240,
7798
+ label: "Notifications",
7799
+ enabled: true,
7800
+ lifecycle: "active",
7801
+ path: "/monitoring/notifications"
7802
+ },
7803
+ "monitoring.submitted-requests": {
7804
+ id: "monitoring.submitted-requests",
7805
+ order: 250,
7806
+ label: "Submitted Requests",
7807
+ enabled: true,
7808
+ lifecycle: "active",
7809
+ path: "/monitoring/requests"
7810
+ },
7811
+ settings: {
7812
+ id: "settings",
7813
+ order: 260,
7814
+ label: "Settings",
7815
+ enabled: true,
7816
+ lifecycle: "active",
7817
+ icon: "settings"
7818
+ },
7819
+ "settings.account": {
7820
+ id: "settings.account",
7821
+ order: 270,
7822
+ label: "Account",
7823
+ enabled: true,
7824
+ lifecycle: "active",
7825
+ path: "/settings/account"
7826
+ },
7827
+ "settings.appearance": {
7828
+ id: "settings.appearance",
7829
+ order: 280,
7830
+ label: "Appearance",
7831
+ enabled: true,
7832
+ lifecycle: "active",
7833
+ path: "/settings/appearance"
7834
+ },
7835
+ "settings.roles": {
7836
+ id: "settings.roles",
7837
+ order: 290,
7838
+ label: "My Roles",
7839
+ enabled: true,
7840
+ lifecycle: "active",
7841
+ path: "/settings/roles"
7842
+ },
7843
+ "settings.organization": {
7844
+ id: "settings.organization",
7845
+ order: 300,
7846
+ label: "Organization",
7847
+ enabled: true,
7848
+ lifecycle: "active",
7849
+ path: "/settings/organization"
7850
+ },
7851
+ "settings.credentials": {
7852
+ id: "settings.credentials",
7853
+ order: 310,
7854
+ label: "Credentials",
7855
+ enabled: true,
7856
+ lifecycle: "active",
7857
+ path: "/settings/credentials"
7858
+ },
7859
+ "settings.api-keys": {
7860
+ id: "settings.api-keys",
7861
+ order: 320,
7862
+ label: "API Keys",
7863
+ enabled: true,
7864
+ lifecycle: "active",
7865
+ path: "/settings/api-keys"
7866
+ },
7867
+ "settings.webhooks": {
7868
+ id: "settings.webhooks",
7869
+ order: 330,
7870
+ label: "Webhooks",
7871
+ enabled: true,
7872
+ lifecycle: "active",
7873
+ path: "/settings/webhooks"
7874
+ },
7875
+ "settings.deployments": {
7876
+ id: "settings.deployments",
7877
+ order: 340,
7878
+ label: "Deployments",
7879
+ enabled: true,
7880
+ lifecycle: "active",
7881
+ path: "/settings/deployments"
7882
+ },
7883
+ admin: {
7884
+ id: "admin",
7885
+ order: 350,
7886
+ label: "Admin",
7887
+ enabled: true,
7888
+ lifecycle: "active",
7889
+ path: "/admin",
7890
+ icon: "admin",
7891
+ requiresAdmin: true
7892
+ },
7893
+ "admin.system-health": {
7894
+ id: "admin.system-health",
7895
+ order: 360,
7896
+ label: "System Health",
7897
+ enabled: true,
7898
+ lifecycle: "active",
7899
+ path: "/admin/system-health"
7900
+ },
7901
+ "admin.organizations": {
7902
+ id: "admin.organizations",
7903
+ order: 370,
7904
+ label: "Organizations",
7905
+ enabled: true,
7906
+ lifecycle: "active",
7907
+ path: "/admin/organizations"
7908
+ },
7909
+ "admin.users": {
7910
+ id: "admin.users",
7911
+ order: 380,
7912
+ label: "Users",
7913
+ enabled: true,
7914
+ lifecycle: "active",
7915
+ path: "/admin/users"
7916
+ },
7917
+ "admin.design-showcase": {
7918
+ id: "admin.design-showcase",
7919
+ order: 390,
7920
+ label: "Design Showcase",
7921
+ enabled: true,
7922
+ lifecycle: "active",
7923
+ path: "/admin/design-showcase"
7924
+ },
7925
+ "admin.debug": {
7926
+ id: "admin.debug",
7927
+ order: 400,
7928
+ label: "Debug",
7929
+ enabled: true,
7930
+ lifecycle: "active",
7931
+ path: "/admin/debug"
7932
+ },
7933
+ archive: {
7934
+ id: "archive",
7935
+ order: 410,
7936
+ label: "Archive",
7937
+ enabled: true,
7938
+ lifecycle: "active",
7939
+ path: "/archive",
7940
+ icon: "archive",
7941
+ devOnly: true
7942
+ },
7943
+ "archive.agent-chat": {
7944
+ id: "archive.agent-chat",
7945
+ order: 420,
7946
+ label: "Agent Chat",
7947
+ enabled: true,
7948
+ lifecycle: "active",
7949
+ path: "/archive/agent-chat"
7950
+ },
7951
+ "archive.execution-runner": {
7952
+ id: "archive.execution-runner",
7953
+ order: 430,
7954
+ label: "Execution Runner",
7955
+ enabled: true,
7956
+ lifecycle: "active",
7957
+ path: "/archive/execution-runner"
7958
+ },
7959
+ seo: {
7960
+ id: "seo",
7961
+ order: 440,
7962
+ label: "SEO",
7963
+ enabled: false,
7964
+ lifecycle: "deprecated",
7965
+ path: "/seo"
7966
+ },
7967
+ knowledge: {
7968
+ id: "knowledge",
7969
+ order: 450,
7970
+ label: "Knowledge",
7971
+ description: "Operational knowledge, playbooks, and strategy docs",
7972
+ enabled: true,
7973
+ lifecycle: "active",
7974
+ color: "teal",
7975
+ icon: "knowledge"
7976
+ },
7977
+ "knowledge.base": {
7978
+ id: "knowledge.base",
7979
+ order: 460,
7980
+ label: "Knowledge Base",
7981
+ enabled: true,
7982
+ lifecycle: "active",
7983
+ path: "/knowledge"
7984
+ }
7985
+ },
7986
+ ontology: DEFAULT_ONTOLOGY_SCOPE,
7987
+ resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
7988
+ topology: DEFAULT_ORGANIZATION_MODEL_TOPOLOGY,
7989
+ actions: DEFAULT_ORGANIZATION_MODEL_ACTIONS,
7990
+ entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
7991
+ policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
7992
+ // Phase 4 (D1): statuses top-level field removed; bridge status mirrors may
7993
+ // still project from System.content, but primary authoring belongs in ontology.
7994
+ knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
7995
+ };
7996
+
7997
+ // ../core/src/business/acquisition/ontology-validation.ts
7998
+ var CRM_PIPELINE_CATALOG_ONTOLOGY_ID = formatOntologyId({
7999
+ scope: "sales.crm",
8000
+ kind: "catalog",
8001
+ localId: "crm.pipeline"
8002
+ });
8003
+ var LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
8004
+ scope: "sales.lead-gen",
8005
+ kind: "catalog",
8006
+ localId: "lead-gen.stage-catalog"
8007
+ });
8008
+ var CRM_DEAL_OBJECT_ONTOLOGY_ID = formatOntologyId({
8009
+ scope: "sales.crm",
8010
+ kind: "object",
8011
+ localId: "crm.deal"
8012
+ });
8013
+ function createCrmPipelineCatalog() {
8014
+ return {
8015
+ id: CRM_PIPELINE_CATALOG_ONTOLOGY_ID,
8016
+ label: CRM_PIPELINE_DEFINITION.label,
8017
+ ownerSystemId: "sales.crm",
8018
+ kind: "pipeline",
8019
+ appliesTo: CRM_DEAL_OBJECT_ONTOLOGY_ID,
8020
+ entries: Object.fromEntries(
8021
+ CRM_PIPELINE_DEFINITION.stages.map((stage, index) => [
8022
+ stage.stageKey,
8023
+ {
8024
+ key: stage.stageKey,
8025
+ label: stage.label,
8026
+ order: (index + 1) * 10,
8027
+ ...stage.color !== void 0 ? { color: stage.color } : {},
8028
+ states: stage.states.map((state) => ({ ...state }))
8029
+ }
8030
+ ])
8031
+ ),
8032
+ legacyPipelineKey: CRM_PIPELINE_DEFINITION.pipelineKey,
8033
+ legacyEntityKey: CRM_PIPELINE_DEFINITION.entityKey
8034
+ };
8035
+ }
8036
+ function createLeadGenStageCatalog() {
8037
+ return {
8038
+ id: LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID,
8039
+ label: "Lead Gen Processing Stages",
8040
+ ownerSystemId: "sales.lead-gen",
8041
+ kind: "processing-stage-catalog",
8042
+ entries: Object.fromEntries(
8043
+ Object.entries(LEAD_GEN_STAGE_CATALOG).map(([key, entry]) => [
8044
+ key,
8045
+ {
8046
+ ...entry
8047
+ }
8048
+ ])
8049
+ ),
8050
+ legacyCatalogKey: "LEAD_GEN_STAGE_CATALOG"
8051
+ };
8052
+ }
8053
+ function isPlainRecord(value) {
8054
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
8055
+ }
8056
+ function mergeBridgeCatalogs(model) {
8057
+ const baseCatalogTypes = model.ontology?.catalogTypes ?? {};
8058
+ const bridgeCatalogTypes = {};
8059
+ if (baseCatalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID] === void 0) {
8060
+ bridgeCatalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID] = createCrmPipelineCatalog();
8061
+ }
8062
+ if (baseCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] === void 0) {
8063
+ bridgeCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] = createLeadGenStageCatalog();
8064
+ }
8065
+ if (Object.keys(bridgeCatalogTypes).length === 0) return model;
8066
+ return {
8067
+ ...model,
8068
+ ontology: {
8069
+ ...model.ontology ?? {},
8070
+ catalogTypes: {
8071
+ ...baseCatalogTypes,
8072
+ ...bridgeCatalogTypes
8073
+ }
8074
+ }
8075
+ };
8076
+ }
8077
+ function compileBusinessOntologyValidationIndex(model = DEFAULT_ORGANIZATION_MODEL) {
8078
+ const compilation = compileOrganizationOntology(mergeBridgeCatalogs(model));
8079
+ if (compilation.diagnostics.length > 0) {
8080
+ const summary = compilation.diagnostics.map((diagnostic) => diagnostic.message).join("; ");
8081
+ throw new Error(`Business ontology validation index failed to compile: ${summary}`);
8082
+ }
8083
+ const crmPipelineCatalog = compilation.ontology.catalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID];
8084
+ const leadGenStageCatalog = compilation.ontology.catalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID];
8085
+ if (crmPipelineCatalog === void 0 || leadGenStageCatalog === void 0) {
8086
+ throw new Error("Business ontology validation index is missing CRM or lead-gen catalog bridge records");
8087
+ }
8088
+ return {
8089
+ ontology: compilation.ontology,
8090
+ crmPipelineCatalog,
8091
+ leadGenStageCatalog,
8092
+ actionTypesByLegacyId: indexActionTypesByLegacyId(compilation.ontology.actionTypes)
8093
+ };
8094
+ }
8095
+ function indexActionTypesByLegacyId(actionTypes) {
8096
+ const byLegacyId = {};
8097
+ for (const actionType of Object.values(actionTypes)) {
8098
+ const legacyActionId = actionType["legacyActionId"];
8099
+ if (typeof legacyActionId === "string") {
8100
+ byLegacyId[legacyActionId] = actionType;
8101
+ }
8102
+ }
8103
+ return byLegacyId;
8104
+ }
8105
+ var BUSINESS_ONTOLOGY_VALIDATION_INDEX = compileBusinessOntologyValidationIndex();
8106
+ function getCatalogEntries(catalog) {
8107
+ return isPlainRecord(catalog.entries) ? catalog.entries : {};
8108
+ }
8109
+ function asCrmStageEntry(key, value) {
8110
+ const record = isPlainRecord(value) ? value : {};
8111
+ const label = typeof record.label === "string" ? record.label : key;
8112
+ const order = typeof record.order === "number" ? record.order : 0;
8113
+ const color = typeof record.color === "string" ? record.color : void 0;
8114
+ const rawStates = Array.isArray(record.states) ? record.states : [];
8115
+ const states = rawStates.flatMap((state) => {
8116
+ if (!isPlainRecord(state) || typeof state.stateKey !== "string") return [];
8117
+ return [
8118
+ {
8119
+ stateKey: state.stateKey,
8120
+ label: typeof state.label === "string" ? state.label : state.stateKey
8121
+ }
8122
+ ];
8123
+ });
8124
+ return {
8125
+ key,
8126
+ label,
8127
+ order,
8128
+ ...color !== void 0 ? { color } : {},
8129
+ states
8130
+ };
8131
+ }
8132
+ function asLeadGenStageEntry(key, value) {
8133
+ const record = isPlainRecord(value) ? value : {};
8134
+ const entity = record.entity === "contact" ? "contact" : "company";
8135
+ const additionalEntities = Array.isArray(record.additionalEntities) ? record.additionalEntities.filter(
8136
+ (item) => item === "company" || item === "contact"
8137
+ ) : void 0;
8138
+ const recordEntity = record.recordEntity === "company" || record.recordEntity === "contact" ? record.recordEntity : void 0;
8139
+ const recordStageKey = typeof record.recordStageKey === "string" ? record.recordStageKey : void 0;
8140
+ return {
8141
+ key: typeof record.key === "string" ? record.key : key,
8142
+ label: typeof record.label === "string" ? record.label : key,
8143
+ description: typeof record.description === "string" ? record.description : "",
8144
+ order: typeof record.order === "number" ? record.order : 0,
8145
+ entity,
8146
+ ...additionalEntities !== void 0 ? { additionalEntities } : {},
8147
+ ...recordEntity !== void 0 ? { recordEntity } : {},
8148
+ ...recordStageKey !== void 0 ? { recordStageKey } : {}
8149
+ };
8150
+ }
8151
+ var CRM_STAGE_KEYS_FROM_ONTOLOGY = Object.keys(
8152
+ getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.crmPipelineCatalog)
8153
+ );
8154
+ var CRM_STATE_KEYS_FROM_ONTOLOGY = Object.values(
8155
+ getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.crmPipelineCatalog)
8156
+ ).flatMap((entry, index) => {
8157
+ const stageKey = CRM_STAGE_KEYS_FROM_ONTOLOGY[index];
8158
+ if (stageKey === void 0) return [];
8159
+ return asCrmStageEntry(stageKey, entry).states.map((state) => state.stateKey);
8160
+ });
8161
+ Object.keys(
8162
+ getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.leadGenStageCatalog)
8163
+ );
8164
+ function getLeadGenStageCatalogFromOntology() {
8165
+ return Object.fromEntries(
8166
+ Object.entries(getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.leadGenStageCatalog)).map(([key, value]) => [
8167
+ key,
8168
+ asLeadGenStageEntry(key, value)
8169
+ ])
8170
+ );
8171
+ }
8172
+ function getLeadGenStageEntry(stageKey) {
8173
+ return getLeadGenStageCatalogFromOntology()[stageKey];
8174
+ }
8175
+ function isLeadGenStageKey(stageKey) {
8176
+ return getLeadGenStageEntry(stageKey) !== void 0;
8177
+ }
8178
+ function isLeadGenRecordStageValidForEntity(stageKey, entity) {
8179
+ const stage = getLeadGenStageEntry(stageKey);
8180
+ return stage !== void 0 && (stage.entity === entity || stage.additionalEntities?.includes(entity) === true || stage.recordEntity === entity);
8181
+ }
8182
+ function getActionMetadata(actionKey) {
8183
+ const actionType = BUSINESS_ONTOLOGY_VALIDATION_INDEX.actionTypesByLegacyId[actionKey];
8184
+ if (actionType === void 0) return void 0;
8185
+ const resourceId = actionType["resourceId"];
8186
+ return {
8187
+ id: actionKey,
8188
+ label: actionType.label ?? actionKey,
8189
+ ...typeof resourceId === "string" ? { resourceId } : {}
8190
+ };
8191
+ }
8192
+ function getCrmActionMetadata(actionKey) {
8193
+ const actionType = BUSINESS_ONTOLOGY_VALIDATION_INDEX.actionTypesByLegacyId[actionKey];
8194
+ return actionType?.ownerSystemId === "sales.crm" ? getActionMetadata(actionKey) : void 0;
8195
+ }
8196
+ function isLeadGenActionKey(actionKey) {
8197
+ return actionKey.startsWith("lead-gen.") && BUSINESS_ONTOLOGY_VALIDATION_INDEX.actionTypesByLegacyId[actionKey] !== void 0;
8198
+ }
8199
+
4849
8200
  // ../core/src/business/acquisition/deal-ownership.ts
4850
8201
  var INBOUND_EVENT_TYPES = ["reply_received"];
4851
8202
  var OUTBOUND_EVENT_TYPES = [
@@ -4904,14 +8255,14 @@ function parseMs(value) {
4904
8255
 
4905
8256
  // ../core/src/business/acquisition/api-schemas.ts
4906
8257
  var ProcessingStageStatusSchema = z.enum(["success", "no_result", "skipped", "error"]);
4907
- var LeadGenStageKeySchema = z.string().refine((value) => Object.prototype.hasOwnProperty.call(LEAD_GEN_STAGE_CATALOG, value), {
8258
+ var LeadGenStageKeySchema = z.string().refine((value) => isLeadGenStageKey(value), {
4908
8259
  message: "processing state key must match LEAD_GEN_STAGE_CATALOG"
4909
8260
  });
4910
- var LeadGenActionKeySchema = z.string().refine((value) => ACTION_REGISTRY.some((c) => c.id === value), {
8261
+ var LeadGenActionKeySchema = z.string().refine((value) => isLeadGenActionKey(value), {
4911
8262
  message: "actionKey must match ACTION_REGISTRY"
4912
8263
  });
4913
- var crmStageKeys = CRM_PIPELINE_DEFINITION.stages.map((stage) => stage.stageKey);
4914
- var crmStateKeys = CRM_PIPELINE_DEFINITION.stages.flatMap((stage) => stage.states.map((state) => state.stateKey));
8264
+ var crmStageKeys = CRM_STAGE_KEYS_FROM_ONTOLOGY;
8265
+ var crmStateKeys = CRM_STATE_KEYS_FROM_ONTOLOGY;
4915
8266
  var CrmStageKeySchema = z.enum(crmStageKeys);
4916
8267
  var CrmStateKeySchema = z.enum(crmStateKeys);
4917
8268
  var ProcessingStateEntrySchema = z.object({
@@ -5166,7 +8517,7 @@ var IcpRubricSchema = z.object({
5166
8517
  customRules: z.string().optional()
5167
8518
  });
5168
8519
  var PipelineStageSchema = z.object({
5169
- key: z.string().refine((value) => Object.prototype.hasOwnProperty.call(LEAD_GEN_STAGE_CATALOG, value), {
8520
+ key: z.string().refine((value) => isLeadGenStageKey(value), {
5170
8521
  message: "pipeline stage key must match LEAD_GEN_STAGE_CATALOG"
5171
8522
  }),
5172
8523
  label: z.string().optional(),
@@ -5638,9 +8989,7 @@ z.object({
5638
8989
  offset: z.coerce.number().int().min(0).default(0)
5639
8990
  }).strict().superRefine((query, ctx) => {
5640
8991
  if (!query.stage) return;
5641
- const stage = LEAD_GEN_STAGE_CATALOG[query.stage];
5642
- const validEntity = stage?.entity === query.entity || stage?.additionalEntities?.includes(query.entity) || stage?.recordEntity === query.entity;
5643
- if (!validEntity) {
8992
+ if (!isLeadGenRecordStageValidForEntity(query.stage, query.entity)) {
5644
8993
  ctx.addIssue({
5645
8994
  code: z.ZodIssueCode.custom,
5646
8995
  message: `stage "${query.stage}" is not valid for ${query.entity} records`,
@@ -5826,56 +9175,44 @@ var ActivityEventSchema = z.discriminatedUnion("type", [
5826
9175
  var SendReplyActionPayloadSchema = z.object({
5827
9176
  replyBody: z.string().trim().min(1).max(1e4)
5828
9177
  }).strict();
9178
+ function crmAction(actionId, runtime) {
9179
+ const metadata = getCrmActionMetadata(actionId);
9180
+ if (!metadata?.resourceId) {
9181
+ throw new Error(`CRM action metadata for "${actionId}" must define resourceId`);
9182
+ }
9183
+ return {
9184
+ key: metadata.id,
9185
+ label: metadata.label,
9186
+ workflowId: metadata.resourceId,
9187
+ ...runtime
9188
+ };
9189
+ }
5829
9190
  var DEFAULT_CRM_ACTIONS = [
5830
- {
5831
- key: "move_to_proposal",
5832
- label: "Move to Proposal",
5833
- isAvailableFor: (deal) => deal.stage_key === "interested",
5834
- workflowId: "move_to_proposal-workflow"
5835
- },
5836
- {
5837
- key: "move_to_closing",
5838
- label: "Move to Closing",
5839
- isAvailableFor: (deal) => deal.stage_key === "proposal",
5840
- workflowId: "move_to_closing-workflow"
5841
- },
5842
- {
5843
- key: "move_to_closed_won",
5844
- label: "Close Won",
5845
- isAvailableFor: (deal) => deal.stage_key === "closing",
5846
- workflowId: "move_to_closed_won-workflow"
5847
- },
5848
- {
5849
- key: "move_to_closed_lost",
5850
- label: "Close Lost",
5851
- isAvailableFor: (deal) => deal.stage_key === "interested" || deal.stage_key === "proposal" || deal.stage_key === "closing",
5852
- workflowId: "move_to_closed_lost-workflow"
5853
- },
5854
- {
5855
- key: "move_to_nurturing",
5856
- label: "Move to Nurturing",
5857
- isAvailableFor: (deal) => deal.stage_key === "interested" || deal.stage_key === "proposal" || deal.stage_key === "closing",
5858
- workflowId: "move_to_nurturing-workflow"
5859
- },
5860
- {
5861
- key: "send_reply",
5862
- label: "Send Reply",
9191
+ crmAction("move_to_proposal", {
9192
+ isAvailableFor: (deal) => deal.stage_key === "interested"
9193
+ }),
9194
+ crmAction("move_to_closing", {
9195
+ isAvailableFor: (deal) => deal.stage_key === "proposal"
9196
+ }),
9197
+ crmAction("move_to_closed_won", {
9198
+ isAvailableFor: (deal) => deal.stage_key === "closing"
9199
+ }),
9200
+ crmAction("move_to_closed_lost", {
9201
+ isAvailableFor: (deal) => deal.stage_key === "interested" || deal.stage_key === "proposal" || deal.stage_key === "closing"
9202
+ }),
9203
+ crmAction("move_to_nurturing", {
9204
+ isAvailableFor: (deal) => deal.stage_key === "interested" || deal.stage_key === "proposal" || deal.stage_key === "closing"
9205
+ }),
9206
+ crmAction("send_reply", {
5863
9207
  isAvailableFor: (deal) => deal.stage_key === "interested" && isOurReplyAction(deal) && (deal.state_key === CRM_DISCOVERY_REPLIED_STATE.stateKey || deal.state_key === CRM_DISCOVERY_LINK_SENT_STATE.stateKey || deal.state_key === CRM_DISCOVERY_NUDGING_STATE.stateKey),
5864
- workflowId: "crm-send-reply-workflow",
5865
9208
  payloadSchema: SendReplyActionPayloadSchema
5866
- },
5867
- {
5868
- key: "send_link",
5869
- label: "Send Booking Link",
5870
- isAvailableFor: (deal) => deal.stage_key === "interested" && deal.state_key === CRM_DISCOVERY_REPLIED_STATE.stateKey,
5871
- workflowId: "crm-send-booking-link-workflow"
5872
- },
5873
- {
5874
- key: "send_nudge",
5875
- label: "Send Nudge",
5876
- isAvailableFor: (deal) => deal.stage_key === "interested" && (deal.state_key === CRM_DISCOVERY_LINK_SENT_STATE.stateKey || deal.state_key === CRM_DISCOVERY_NUDGING_STATE.stateKey),
5877
- workflowId: "crm-send-nudge-workflow"
5878
- },
9209
+ }),
9210
+ crmAction("send_link", {
9211
+ isAvailableFor: (deal) => deal.stage_key === "interested" && deal.state_key === CRM_DISCOVERY_REPLIED_STATE.stateKey
9212
+ }),
9213
+ crmAction("send_nudge", {
9214
+ isAvailableFor: (deal) => deal.stage_key === "interested" && (deal.state_key === CRM_DISCOVERY_LINK_SENT_STATE.stateKey || deal.state_key === CRM_DISCOVERY_NUDGING_STATE.stateKey)
9215
+ }),
5879
9216
  {
5880
9217
  key: "mark_no_show",
5881
9218
  label: "Mark No-Show",
@@ -5885,12 +9222,9 @@ var DEFAULT_CRM_ACTIONS = [
5885
9222
  // event captures operator intent and distinguishes the manual variant from the timed one.
5886
9223
  workflowId: "mark_no_show-workflow"
5887
9224
  },
5888
- {
5889
- key: "rebook",
5890
- label: "Rebook",
5891
- isAvailableFor: (deal) => deal.stage_key === "interested" && deal.state_key === CRM_DISCOVERY_BOOKING_CANCELLED_STATE.stateKey,
5892
- workflowId: "crm-rebook-workflow"
5893
- }
9225
+ crmAction("rebook", {
9226
+ isAvailableFor: (deal) => deal.stage_key === "interested" && deal.state_key === CRM_DISCOVERY_BOOKING_CANCELLED_STATE.stateKey
9227
+ })
5894
9228
  ];
5895
9229
  function deriveActions(deal, actions = DEFAULT_CRM_ACTIONS) {
5896
9230
  return actions.filter((a) => a.isAvailableFor(deal)).map(({ key, label, payloadSchema }) => ({ key, label, payloadSchema }));
@@ -5904,4 +9238,4 @@ function isOurReplyAction(deal) {
5904
9238
  var listBuilderStageKeys = Object.keys(LEAD_GEN_STAGE_CATALOG);
5905
9239
  var ListBuilderStageKeySchema = z.enum(listBuilderStageKeys);
5906
9240
 
5907
- export { ActivityEventSchema, BuildPlanSnapshotStepSchema, ProspectingBuildTemplateSchema as BuildTemplateSchema, CRM_PIPELINE_DEFINITION, CrmStageKeySchema, CrmStateKeySchema, DEFAULT_CRM_ACTIONS, EmailSchema, ExecutionError, LEAD_GEN_STAGE_CATALOG, ListBuilderStageKeySchema, ProcessingStageStatusSchema, RegistryValidationError, ResourceRegistry, StepType, ToolingError, deriveActions, validateResourceGovernance };
9241
+ export { ActivityEventSchema, BuildPlanSnapshotStepSchema, ProspectingBuildTemplateSchema as BuildTemplateSchema, CRM_PIPELINE_DEFINITION, CrmStageKeySchema, CrmStateKeySchema, DEFAULT_CRM_ACTIONS, EmailSchema, ExecutionError, LEAD_GEN_STAGE_CATALOG, ListBuilderStageKeySchema, ProcessingStageStatusSchema, RegistryValidationError, ResourceRegistry, StepType, ToolingError, bindResourceDescriptor, defineResource, defineResourceOntology, defineResources, defineTopology, defineTopologyRelationship, deriveActions, parseTopologyNodeRef, topologyRef, topologyRelationship, validateResourceGovernance };