@elevasis/sdk 1.24.0 → 1.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/cli.cjs +875 -834
  2. package/dist/index.d.ts +4857 -4547
  3. package/dist/index.js +564 -2338
  4. package/dist/node/index.d.ts +693 -1356
  5. package/dist/node/index.js +1 -1
  6. package/dist/test-utils/index.d.ts +4186 -4139
  7. package/dist/test-utils/index.js +694 -2769
  8. package/dist/types/worker/adapters/clickup.d.ts +22 -0
  9. package/dist/types/worker/adapters/index.d.ts +1 -0
  10. package/dist/types/worker/index.d.ts +3 -2
  11. package/dist/types/worker/platform.d.ts +2 -2
  12. package/dist/worker/index.js +427 -2803
  13. package/package.json +2 -2
  14. package/reference/_navigation.md +11 -1
  15. package/reference/_reference-manifest.json +70 -0
  16. package/reference/claude-config/rules/organization-model.md +12 -1
  17. package/reference/claude-config/rules/organization-os.md +12 -1
  18. package/reference/claude-config/skills/om/SKILL.md +13 -5
  19. package/reference/claude-config/skills/om/operations/codify-level-a.md +109 -100
  20. package/reference/claude-config/skills/om/operations/customers.md +10 -6
  21. package/reference/claude-config/skills/om/operations/features.md +7 -3
  22. package/reference/claude-config/skills/om/operations/goals.md +10 -6
  23. package/reference/claude-config/skills/om/operations/identity.md +8 -5
  24. package/reference/claude-config/skills/om/operations/labels.md +17 -1
  25. package/reference/claude-config/skills/om/operations/offerings.md +11 -7
  26. package/reference/claude-config/skills/om/operations/roles.md +11 -7
  27. package/reference/claude-config/skills/om/operations/techStack.md +10 -2
  28. package/reference/claude-config/sync-notes/2026-05-20-om-define-helpers.md +32 -0
  29. package/reference/claude-config/sync-notes/2026-05-22-access-model-and-right-panel.md +43 -0
  30. package/reference/claude-config/sync-notes/2026-05-22-lead-gen-tenant-config.md +40 -0
  31. package/reference/claude-config/sync-notes/2026-05-22-org-model-multi-file-split.md +61 -0
  32. package/reference/cli-management.mdx +539 -0
  33. package/reference/cli.mdx +579 -808
  34. package/reference/concepts.mdx +134 -146
  35. package/reference/deployment/api.mdx +296 -297
  36. package/reference/deployment/command-center.mdx +208 -209
  37. package/reference/deployment/index.mdx +194 -195
  38. package/reference/deployment/provided-features.mdx +110 -107
  39. package/reference/deployment/ui-execution.mdx +249 -250
  40. package/reference/framework/index.mdx +111 -195
  41. package/reference/framework/resource-documentation.mdx +90 -0
  42. package/reference/framework/tutorial-system.mdx +135 -135
  43. package/reference/getting-started.mdx +141 -142
  44. package/reference/index.mdx +95 -106
  45. package/reference/packages/ui/src/auth/README.md +6 -6
  46. package/reference/platform-tools/adapters-integration.mdx +300 -301
  47. package/reference/platform-tools/adapters-platform.mdx +552 -553
  48. package/reference/platform-tools/index.mdx +216 -217
  49. package/reference/platform-tools/type-safety.mdx +82 -82
  50. package/reference/resources/index.mdx +348 -349
  51. package/reference/resources/patterns.mdx +446 -449
  52. package/reference/resources/types.mdx +115 -116
  53. package/reference/roadmap.mdx +164 -165
  54. package/reference/rules/organization-model.md +14 -0
  55. package/reference/runtime.mdx +172 -173
  56. package/reference/scaffold/operations/propagation-pipeline.md +1 -1
  57. package/reference/scaffold/recipes/customize-crm-actions.md +45 -46
  58. package/reference/scaffold/recipes/extend-crm.md +253 -255
  59. package/reference/scaffold/recipes/extend-lead-gen.md +130 -77
  60. package/reference/scaffold/recipes/index.md +43 -44
  61. package/reference/scaffold/reference/contracts.md +1275 -1432
  62. package/reference/scaffold/reference/glossary.md +8 -6
  63. package/reference/scaffold/ui/feature-flags-and-gating.md +59 -46
  64. package/reference/scaffold/ui/feature-shell.mdx +11 -11
  65. package/reference/scaffold/ui/recipes.md +24 -24
  66. package/reference/troubleshooting.mdx +222 -223
package/dist/index.js CHANGED
@@ -21,549 +21,6 @@ function defineStep(step) {
21
21
  function defineWorkflow(workflow) {
22
22
  return workflow;
23
23
  }
24
- var ORGANIZATION_MODEL_ICON_TOKENS = [
25
- // Navigation / app areas
26
- "dashboard",
27
- "calendar",
28
- "sales",
29
- "crm",
30
- "lead-gen",
31
- "projects",
32
- "clients",
33
- "operations",
34
- "monitoring",
35
- "knowledge",
36
- "settings",
37
- "admin",
38
- "archive",
39
- "business",
40
- "finance",
41
- "platform",
42
- "seo",
43
- // Knowledge kinds
44
- "playbook",
45
- "strategy",
46
- "reference",
47
- // Resource kinds
48
- "agent",
49
- "workflow",
50
- "integration",
51
- "database",
52
- "user",
53
- "team",
54
- // Integration specifics
55
- "gmail",
56
- "google-sheets",
57
- "attio",
58
- // Surface / UI views
59
- "overview",
60
- "command-view",
61
- "command-queue",
62
- "pipeline",
63
- "lists",
64
- "resources",
65
- // Actions
66
- "approve",
67
- "reject",
68
- "retry",
69
- "edit",
70
- "view",
71
- "launch",
72
- "message",
73
- "escalate",
74
- "promote",
75
- "submit",
76
- "email",
77
- // Status
78
- "success",
79
- "error",
80
- "warning",
81
- "info",
82
- "pending",
83
- // OM / UI group icons
84
- "bolt",
85
- "building",
86
- "briefcase",
87
- "apps",
88
- "graph",
89
- "shield",
90
- "users",
91
- "chart-bar",
92
- "search"
93
- ];
94
- var CustomIconTokenSchema = z.string().trim().max(80).regex(
95
- /^custom\.[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
96
- 'Custom icon tokens must start with "custom." followed by lowercase alphanumeric segments'
97
- );
98
- var OrganizationModelBuiltinIconTokenSchema = z.enum(ORGANIZATION_MODEL_ICON_TOKENS);
99
- var OrganizationModelIconTokenSchema = z.union([
100
- OrganizationModelBuiltinIconTokenSchema,
101
- CustomIconTokenSchema
102
- ]);
103
-
104
- // ../core/src/organization-model/domains/shared.ts
105
- var ModelIdSchema = z.string().trim().min(1).max(100).regex(/^[a-z0-9]+(?:[-._][a-z0-9]+)*$/, "IDs must be lowercase and use -, _, or . separators");
106
- var LabelSchema = z.string().trim().min(1).max(120);
107
- var DescriptionSchema = z.string().trim().min(1).max(2e3);
108
- var ColorTokenSchema = z.string().trim().min(1).max(50);
109
- var IconNameSchema = OrganizationModelIconTokenSchema;
110
- var PathSchema = z.string().trim().startsWith("/").max(300);
111
- var ReferenceIdsSchema = z.array(ModelIdSchema).default([]);
112
- var DisplayMetadataSchema = z.object({
113
- label: LabelSchema,
114
- description: DescriptionSchema.optional(),
115
- color: ColorTokenSchema.optional(),
116
- icon: IconNameSchema.optional()
117
- });
118
- var TechStackEntrySchema = z.object({
119
- /** Name of the external platform (e.g. "HubSpot", "Stripe", "Notion"). */
120
- platform: z.string().trim().min(1).max(200),
121
- /** Free-form description of what this integration is used for. */
122
- purpose: z.string().trim().min(1).max(500),
123
- /**
124
- * Health of the credential backing this integration.
125
- * - configured: credential present and valid
126
- * - pending: not yet set up
127
- * - expired: credential existed but has lapsed
128
- * - missing: expected but not present
129
- */
130
- credentialStatus: z.enum(["configured", "pending", "expired", "missing"]),
131
- /**
132
- * Whether this integration is the primary system of record for its domain
133
- * (e.g. HubSpot is SoR for contacts). Defaults to false.
134
- */
135
- isSystemOfRecord: z.boolean().default(false)
136
- });
137
- DisplayMetadataSchema.extend({
138
- id: ModelIdSchema,
139
- resourceId: z.string().trim().min(1).max(255),
140
- resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
141
- systemIds: ReferenceIdsSchema,
142
- entityIds: ReferenceIdsSchema,
143
- surfaceIds: ReferenceIdsSchema,
144
- actionIds: ReferenceIdsSchema,
145
- /** Optional tech-stack metadata for external-SaaS integrations. */
146
- techStack: TechStackEntrySchema.optional()
147
- });
148
-
149
- // ../core/src/organization-model/domains/branding.ts
150
- var OrganizationModelBrandingSchema = z.object({
151
- organizationName: LabelSchema,
152
- productName: LabelSchema,
153
- shortName: z.string().trim().min(1).max(40),
154
- description: DescriptionSchema.optional(),
155
- logos: z.object({
156
- light: z.string().trim().min(1).max(2048).optional(),
157
- dark: z.string().trim().min(1).max(2048).optional()
158
- }).default({})
159
- });
160
- var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
161
- organizationName: "Default Organization",
162
- productName: "Elevasis",
163
- shortName: "Elevasis",
164
- logos: {}
165
- };
166
- var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
167
- z.object({
168
- id: ModelIdSchema,
169
- label: LabelSchema,
170
- path: PathSchema,
171
- surfaceType: SurfaceTypeSchema,
172
- description: DescriptionSchema.optional(),
173
- enabled: z.boolean().default(true),
174
- devOnly: z.boolean().optional(),
175
- icon: IconNameSchema.optional(),
176
- systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
177
- entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
178
- resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
179
- actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
180
- parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
181
- });
182
- var SidebarSurfaceTargetsSchema = z.object({
183
- systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
184
- entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
185
- resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
186
- actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
187
- }).default({});
188
- var SidebarNodeSchema = z.lazy(
189
- () => z.discriminatedUnion("type", [
190
- z.object({
191
- type: z.literal("group"),
192
- label: LabelSchema,
193
- description: DescriptionSchema.optional(),
194
- icon: IconNameSchema.optional(),
195
- order: z.number().int().optional(),
196
- children: z.record(z.string(), SidebarNodeSchema).default({})
197
- }),
198
- z.object({
199
- type: z.literal("surface"),
200
- label: LabelSchema,
201
- path: PathSchema,
202
- surfaceType: SurfaceTypeSchema,
203
- description: DescriptionSchema.optional(),
204
- icon: IconNameSchema.optional(),
205
- order: z.number().int().optional(),
206
- targets: SidebarSurfaceTargetsSchema.optional(),
207
- devOnly: z.boolean().optional(),
208
- requiresAdmin: z.boolean().optional()
209
- })
210
- ])
211
- );
212
- var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
213
- var SidebarNavigationSchema = z.object({
214
- primary: SidebarSectionSchema,
215
- bottom: SidebarSectionSchema
216
- }).default({ primary: {}, bottom: {} });
217
- var OrganizationModelNavigationSchema = z.object({
218
- sidebar: SidebarNavigationSchema
219
- }).default({ sidebar: { primary: {}, bottom: {} } });
220
- z.object({
221
- id: ModelIdSchema,
222
- label: LabelSchema,
223
- placement: z.string().trim().min(1).max(50),
224
- surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
225
- });
226
- var BusinessHoursDaySchema = z.object({
227
- open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
228
- close: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format")
229
- });
230
- var BusinessHoursSchema = z.object({
231
- monday: BusinessHoursDaySchema.optional(),
232
- tuesday: BusinessHoursDaySchema.optional(),
233
- wednesday: BusinessHoursDaySchema.optional(),
234
- thursday: BusinessHoursDaySchema.optional(),
235
- friday: BusinessHoursDaySchema.optional(),
236
- saturday: BusinessHoursDaySchema.optional(),
237
- sunday: BusinessHoursDaySchema.optional()
238
- }).default({});
239
- var IdentityDomainSchema = z.object({
240
- /** Why the organization exists — one or two plain-language sentences. */
241
- mission: z.string().trim().max(1e3).default(""),
242
- /** Long-term direction the organization is moving toward. */
243
- vision: z.string().trim().max(1e3).default(""),
244
- /** Legal registered name of the entity. */
245
- legalName: z.string().trim().max(200).default(""),
246
- /**
247
- * Type of legal entity (e.g. "LLC", "Corporation", "Sole Proprietor",
248
- * "Non-profit"). Free-form string so it covers any jurisdiction.
249
- */
250
- entityType: z.string().trim().max(100).default(""),
251
- /**
252
- * Primary jurisdiction of registration or operation
253
- * (e.g. "United States – Delaware", "Canada – Ontario").
254
- */
255
- jurisdiction: z.string().trim().max(200).default(""),
256
- /**
257
- * Industry category — broad classification (e.g. "Marketing Agency",
258
- * "Software / SaaS", "Professional Services").
259
- */
260
- industryCategory: z.string().trim().max(200).default(""),
261
- /**
262
- * Geographic focus — where the organization primarily operates or serves
263
- * (e.g. "North America", "Global", "Southeast Asia").
264
- */
265
- geographicFocus: z.string().trim().max(200).default(""),
266
- /**
267
- * IANA timezone identifier for the organization's primary operating timezone
268
- * (e.g. "America/Los_Angeles", "Europe/London", "UTC").
269
- */
270
- timeZone: z.string().trim().max(100).default("UTC"),
271
- /** Typical operating hours per day of week. Empty object means not configured. */
272
- businessHours: BusinessHoursSchema,
273
- /**
274
- * Long-form markdown capturing client context, problem narrative, and domain
275
- * background. Populated by /setup; surfaced to agents as organizational context.
276
- * Optional — many projects have no external client.
277
- */
278
- clientBrief: z.string().trim().default("")
279
- });
280
- var DEFAULT_ORGANIZATION_MODEL_IDENTITY = {
281
- mission: "",
282
- vision: "",
283
- legalName: "",
284
- entityType: "",
285
- jurisdiction: "",
286
- industryCategory: "",
287
- geographicFocus: "",
288
- timeZone: "UTC",
289
- businessHours: {},
290
- clientBrief: ""
291
- };
292
- var FirmographicsSchema = z.object({
293
- /** Industry vertical (e.g. "Marketing Agency", "Legal", "Real Estate"). */
294
- industry: z.string().trim().max(200).optional(),
295
- /**
296
- * Company headcount band (e.g. "1–10", "11–50", "51–200", "200+").
297
- * Free-form string to accommodate any band notation.
298
- */
299
- companySize: z.string().trim().max(100).optional(),
300
- /**
301
- * Primary geographic region the segment operates in or is targeted from
302
- * (e.g. "North America", "Europe", "Global").
303
- */
304
- region: z.string().trim().max(200).optional()
305
- });
306
- var CustomerSegmentSchema = z.object({
307
- /** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
308
- id: z.string().trim().min(1).max(100),
309
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
310
- order: z.number(),
311
- /** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
312
- name: z.string().trim().max(200).default(""),
313
- /** One or two sentences describing who this segment is. */
314
- description: z.string().trim().max(2e3).default(""),
315
- /**
316
- * The primary job(s) this segment is trying to get done — the goal they hire
317
- * a product/service to accomplish. Plain-language narrative or bullet list.
318
- */
319
- jobsToBeDone: z.string().trim().max(2e3).default(""),
320
- /**
321
- * Pains — frustrations, obstacles, and risks the segment experiences
322
- * when trying to accomplish their jobs-to-be-done.
323
- */
324
- pains: z.array(z.string().trim().max(500)).default([]),
325
- /**
326
- * Gains — outcomes and benefits the segment desires; positive motivators
327
- * beyond merely resolving pains.
328
- */
329
- gains: z.array(z.string().trim().max(500)).default([]),
330
- /** Firmographic profile for targeting and filtering. */
331
- firmographics: FirmographicsSchema.default({}),
332
- /**
333
- * Value proposition — one or two sentences stating why this organization's
334
- * offering is uniquely suited for this segment's needs.
335
- */
336
- valueProp: z.string().trim().max(2e3).default("")
337
- });
338
- var CustomersDomainSchema = z.record(z.string(), CustomerSegmentSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
339
- message: "Each segment entry id must match its map key"
340
- }).default({});
341
- var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {};
342
- var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]).meta({ label: "Pricing model", color: "green" });
343
- var ProductSchema = z.object({
344
- /** Stable unique identifier for the product (e.g. "product-starter-plan"). */
345
- id: z.string().trim().min(1).max(100),
346
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
347
- order: z.number(),
348
- /** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
349
- name: z.string().trim().max(200).default(""),
350
- /** One or two sentences describing what this product/service delivers. */
351
- description: z.string().trim().max(2e3).default(""),
352
- /**
353
- * How this product is priced:
354
- * - "one-time" — single purchase (setup fee, project fee)
355
- * - "subscription" — recurring (monthly/annual SaaS, retainer)
356
- * - "usage-based" — metered by consumption (API calls, seats)
357
- * - "custom" — negotiated or bespoke pricing
358
- */
359
- pricingModel: PricingModelSchema.default("custom"),
360
- /** Base price amount (≥ 0). Currency unit defined by `currency`. */
361
- price: z.number().min(0).default(0),
362
- /**
363
- * ISO 4217 currency code (e.g. "USD", "EUR", "GBP").
364
- * Free-form string to accommodate any currency; defaults to "USD".
365
- */
366
- currency: z.string().trim().max(10).default("USD"),
367
- /**
368
- * IDs of customer segments this product targets.
369
- * Each id must reference a declared `customers.segments[].id`.
370
- * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
371
- */
372
- targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
373
- /**
374
- * Optional: ID of the platform system responsible for delivering this product.
375
- * When present, must reference a declared `systems.systems[].id`.
376
- * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
377
- */
378
- deliveryFeatureId: z.string().trim().min(1).optional()
379
- });
380
- var OfferingsDomainSchema = z.record(z.string(), ProductSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
381
- message: "Each product entry id must match its map key"
382
- }).default({});
383
- var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {};
384
- var EntityIdSchema = ModelIdSchema;
385
- var EntityLinkKindSchema = z.enum(["belongs-to", "has-many", "has-one", "many-to-many"]).meta({ label: "Link kind" });
386
- var EntityLinkSchema = z.object({
387
- toEntity: EntityIdSchema.meta({ ref: "entity" }),
388
- kind: EntityLinkKindSchema,
389
- via: z.string().trim().min(1).max(255).optional(),
390
- label: LabelSchema.optional()
391
- });
392
- var EntitySchema = z.object({
393
- id: EntityIdSchema,
394
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
395
- order: z.number(),
396
- label: LabelSchema,
397
- description: DescriptionSchema.optional(),
398
- ownedBySystemId: ModelIdSchema.meta({ ref: "system" }),
399
- table: z.string().trim().min(1).max(255).optional(),
400
- rowSchema: ModelIdSchema.optional(),
401
- stateCatalogId: ModelIdSchema.optional(),
402
- links: z.array(EntityLinkSchema).optional()
403
- });
404
- var EntitiesDomainSchema = z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
405
- message: "Each entity entry id must match its map key"
406
- }).default({});
407
- var ENTITY_ENTRY_INPUTS = [
408
- {
409
- id: "crm.deal",
410
- order: 10,
411
- label: "Deal",
412
- description: "A CRM opportunity or sales pipeline record.",
413
- ownedBySystemId: "sales.crm",
414
- table: "crm_deals",
415
- stateCatalogId: "crm.pipeline",
416
- links: [{ toEntity: "crm.contact", kind: "has-many", via: "deal_contacts", label: "contacts" }]
417
- },
418
- {
419
- id: "crm.contact",
420
- order: 20,
421
- label: "CRM Contact",
422
- description: "A person associated with a CRM relationship or deal.",
423
- ownedBySystemId: "sales.crm",
424
- table: "crm_contacts"
425
- },
426
- {
427
- id: "leadgen.list",
428
- order: 30,
429
- label: "Lead List",
430
- description: "A prospecting list that groups companies and contacts for acquisition workflows.",
431
- ownedBySystemId: "sales.lead-gen",
432
- table: "acq_lists",
433
- links: [
434
- { toEntity: "leadgen.company", kind: "has-many", via: "acq_list_companies", label: "companies" },
435
- { toEntity: "leadgen.contact", kind: "has-many", via: "acq_list_members", label: "contacts" }
436
- ]
437
- },
438
- {
439
- id: "leadgen.company",
440
- order: 40,
441
- label: "Lead Company",
442
- description: "A company record sourced, enriched, and qualified during prospecting.",
443
- ownedBySystemId: "sales.lead-gen",
444
- table: "acq_list_companies",
445
- stateCatalogId: "lead-gen.company",
446
- links: [
447
- { toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
448
- { toEntity: "leadgen.contact", kind: "has-many", via: "company_id", label: "contacts" }
449
- ]
450
- },
451
- {
452
- id: "leadgen.contact",
453
- order: 50,
454
- label: "Lead Contact",
455
- description: "A prospect contact discovered or enriched during lead generation.",
456
- ownedBySystemId: "sales.lead-gen",
457
- table: "acq_list_members",
458
- stateCatalogId: "lead-gen.contact",
459
- links: [
460
- { toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
461
- { toEntity: "leadgen.company", kind: "belongs-to", via: "company_id", label: "company" }
462
- ]
463
- },
464
- {
465
- id: "delivery.project",
466
- order: 60,
467
- label: "Project",
468
- description: "A client delivery project.",
469
- ownedBySystemId: "projects",
470
- table: "projects",
471
- links: [
472
- { toEntity: "delivery.milestone", kind: "has-many", via: "project_id", label: "milestones" },
473
- { toEntity: "delivery.task", kind: "has-many", via: "project_id", label: "tasks" }
474
- ]
475
- },
476
- {
477
- id: "delivery.milestone",
478
- order: 70,
479
- label: "Milestone",
480
- description: "A delivery checkpoint within a project.",
481
- ownedBySystemId: "projects",
482
- table: "project_milestones",
483
- links: [
484
- { toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
485
- { toEntity: "delivery.task", kind: "has-many", via: "milestone_id", label: "tasks" }
486
- ]
487
- },
488
- {
489
- id: "delivery.task",
490
- order: 80,
491
- label: "Task",
492
- description: "A delivery task that can move through the task status catalog.",
493
- ownedBySystemId: "projects",
494
- table: "project_tasks",
495
- stateCatalogId: "delivery.task",
496
- links: [
497
- { toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
498
- { toEntity: "delivery.milestone", kind: "belongs-to", via: "milestone_id", label: "milestone" }
499
- ]
500
- }
501
- ];
502
- var DEFAULT_ORGANIZATION_MODEL_ENTITIES = Object.fromEntries(
503
- ENTITY_ENTRY_INPUTS.map((entity) => {
504
- const parsed = EntitySchema.parse(entity);
505
- return [parsed.id, parsed];
506
- })
507
- );
508
-
509
- // ../core/src/organization-model/domains/actions.ts
510
- var ActionResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
511
- z.enum(["slash-command", "mcp-tool", "api-endpoint", "script-execution"]).meta({ label: "Invocation kind" });
512
- var ActionIdSchema = ModelIdSchema;
513
- var ActionScopeSchema = z.union([
514
- z.literal("global"),
515
- z.object({
516
- domain: ModelIdSchema
517
- })
518
- ]);
519
- var ActionRefSchema = z.object({
520
- actionId: ActionIdSchema.meta({ ref: "action" }),
521
- intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
522
- });
523
- var SlashCommandInvocationSchema = z.object({
524
- kind: z.literal("slash-command"),
525
- command: z.string().trim().min(1).max(200).regex(/^\/[^\s].*$/, "Slash commands must start with /"),
526
- toolFactory: ModelIdSchema.optional()
527
- });
528
- var McpToolInvocationSchema = z.object({
529
- kind: z.literal("mcp-tool"),
530
- server: ModelIdSchema,
531
- name: ModelIdSchema
532
- });
533
- var ApiEndpointInvocationSchema = z.object({
534
- kind: z.literal("api-endpoint"),
535
- method: z.enum(["GET", "POST", "PATCH", "DELETE"]).meta({ label: "HTTP method" }),
536
- path: z.string().trim().startsWith("/").max(500),
537
- requestSchema: ModelIdSchema.optional(),
538
- responseSchema: ModelIdSchema.optional()
539
- });
540
- var ScriptExecutionInvocationSchema = z.object({
541
- kind: z.literal("script-execution"),
542
- resourceId: ActionResourceIdSchema
543
- });
544
- var ActionInvocationSchema = z.discriminatedUnion("kind", [
545
- SlashCommandInvocationSchema,
546
- McpToolInvocationSchema,
547
- ApiEndpointInvocationSchema,
548
- ScriptExecutionInvocationSchema
549
- ]);
550
- var ActionSchema = z.object({
551
- id: ActionIdSchema,
552
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
553
- order: z.number(),
554
- label: LabelSchema,
555
- description: DescriptionSchema.optional(),
556
- scope: ActionScopeSchema.default("global"),
557
- resourceId: ActionResourceIdSchema.optional(),
558
- affects: z.array(EntityIdSchema.meta({ ref: "entity" })).optional(),
559
- invocations: z.array(ActionInvocationSchema).default([]),
560
- knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
561
- lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
562
- });
563
- var ActionsDomainSchema = z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
564
- message: "Each action entry id must match its map key"
565
- }).default({});
566
- var DEFAULT_ORGANIZATION_MODEL_ACTIONS = {};
567
24
  var OntologyKindSchema = z.enum([
568
25
  "object",
569
26
  "link",
@@ -661,30 +118,6 @@ var OntologyScopeSchema = z.object({
661
118
  groups: z.record(OntologyIdSchema, OntologyGroupSchema).default({}).optional(),
662
119
  surfaces: z.record(OntologyIdSchema, OntologySurfaceTypeSchema).default({}).optional()
663
120
  }).default({});
664
- var DEFAULT_ONTOLOGY_SCOPE = {
665
- valueTypes: {
666
- "global:value-type/uuid": {
667
- id: "global:value-type/uuid",
668
- label: "UUID",
669
- primitive: "string"
670
- },
671
- "global:value-type/text": {
672
- id: "global:value-type/text",
673
- label: "Text",
674
- primitive: "string"
675
- },
676
- "global:value-type/url": {
677
- id: "global:value-type/url",
678
- label: "URL",
679
- primitive: "string"
680
- },
681
- "global:value-type/email": {
682
- id: "global:value-type/email",
683
- label: "Email",
684
- primitive: "string"
685
- }
686
- }
687
- };
688
121
  var SCOPE_KIND = {
689
122
  objectTypes: "object",
690
123
  linkTypes: "link",
@@ -698,16 +131,6 @@ var SCOPE_KIND = {
698
131
  surfaces: "surface"
699
132
  };
700
133
  var SCOPE_KEYS = Object.keys(SCOPE_KIND);
701
- function listResolvedOntologyRecords(index) {
702
- return SCOPE_KEYS.flatMap((scopeKey) => {
703
- const kind = SCOPE_KIND[scopeKey];
704
- return Object.entries(index[scopeKey]).sort(([leftId], [rightId]) => leftId.localeCompare(rightId)).map(([id, record]) => ({
705
- id,
706
- kind,
707
- record
708
- }));
709
- });
710
- }
711
134
  function originFromContext(context) {
712
135
  return {
713
136
  kind: context.kind,
@@ -917,6 +340,231 @@ function compileOrganizationOntology(model) {
917
340
  return { ontology: sortResolvedOntologyIndex(ontology), diagnostics };
918
341
  }
919
342
 
343
+ // ../core/src/organization-model/helpers.ts
344
+ function childSystemsOf2(system) {
345
+ return system.systems ?? system.subsystems ?? {};
346
+ }
347
+ function listAllSystems(model) {
348
+ const results = [];
349
+ function walk(map, prefix) {
350
+ for (const [localId, system] of Object.entries(map)) {
351
+ const fullPath = prefix ? `${prefix}.${localId}` : localId;
352
+ results.push({ path: fullPath, system });
353
+ const childSystems = childSystemsOf2(system);
354
+ if (Object.keys(childSystems).length > 0) {
355
+ walk(childSystems, fullPath);
356
+ }
357
+ }
358
+ }
359
+ walk(model.systems, "");
360
+ return results;
361
+ }
362
+ var ORGANIZATION_MODEL_ICON_TOKENS = [
363
+ // Navigation / app areas
364
+ "dashboard",
365
+ "calendar",
366
+ "sales",
367
+ "crm",
368
+ "lead-gen",
369
+ "projects",
370
+ "clients",
371
+ "operations",
372
+ "monitoring",
373
+ "knowledge",
374
+ "settings",
375
+ "admin",
376
+ "archive",
377
+ "business",
378
+ "finance",
379
+ "platform",
380
+ "seo",
381
+ // Knowledge kinds
382
+ "playbook",
383
+ "strategy",
384
+ "reference",
385
+ // Resource kinds
386
+ "agent",
387
+ "workflow",
388
+ "integration",
389
+ "database",
390
+ "user",
391
+ "team",
392
+ // Integration specifics
393
+ "gmail",
394
+ "google-sheets",
395
+ "attio",
396
+ // Surface / UI views
397
+ "overview",
398
+ "command-view",
399
+ "command-queue",
400
+ "pipeline",
401
+ "lists",
402
+ "resources",
403
+ // Actions
404
+ "approve",
405
+ "reject",
406
+ "retry",
407
+ "edit",
408
+ "view",
409
+ "launch",
410
+ "message",
411
+ "escalate",
412
+ "promote",
413
+ "submit",
414
+ "email",
415
+ // Status
416
+ "success",
417
+ "error",
418
+ "warning",
419
+ "info",
420
+ "pending",
421
+ // OM / UI group icons
422
+ "bolt",
423
+ "building",
424
+ "briefcase",
425
+ "apps",
426
+ "graph",
427
+ "shield",
428
+ "users",
429
+ "chart-bar",
430
+ "search"
431
+ ];
432
+ var CustomIconTokenSchema = z.string().trim().max(80).regex(
433
+ /^custom\.[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
434
+ 'Custom icon tokens must start with "custom." followed by lowercase alphanumeric segments'
435
+ );
436
+ var OrganizationModelBuiltinIconTokenSchema = z.enum(ORGANIZATION_MODEL_ICON_TOKENS);
437
+ var OrganizationModelIconTokenSchema = z.union([
438
+ OrganizationModelBuiltinIconTokenSchema,
439
+ CustomIconTokenSchema
440
+ ]);
441
+
442
+ // ../core/src/organization-model/domains/shared.ts
443
+ var ModelIdSchema = z.string().trim().min(1).max(100).regex(/^[a-z0-9]+(?:[-._][a-z0-9]+)*$/, "IDs must be lowercase and use -, _, or . separators");
444
+ var LabelSchema = z.string().trim().min(1).max(120);
445
+ var DescriptionSchema = z.string().trim().min(1).max(2e3);
446
+ var ColorTokenSchema = z.string().trim().min(1).max(50);
447
+ var IconNameSchema = OrganizationModelIconTokenSchema;
448
+ var PathSchema = z.string().trim().startsWith("/").max(300);
449
+ var ReferenceIdsSchema = z.array(ModelIdSchema).default([]);
450
+ var DisplayMetadataSchema = z.object({
451
+ label: LabelSchema,
452
+ description: DescriptionSchema.optional(),
453
+ color: ColorTokenSchema.optional(),
454
+ icon: IconNameSchema.optional()
455
+ });
456
+ var TechStackEntrySchema = z.object({
457
+ /** Name of the external platform (e.g. "HubSpot", "Stripe", "Notion"). */
458
+ platform: z.string().trim().min(1).max(200),
459
+ /** Free-form description of what this integration is used for. */
460
+ purpose: z.string().trim().min(1).max(500),
461
+ /**
462
+ * Health of the credential backing this integration.
463
+ * - configured: credential present and valid
464
+ * - pending: not yet set up
465
+ * - expired: credential existed but has lapsed
466
+ * - missing: expected but not present
467
+ */
468
+ credentialStatus: z.enum(["configured", "pending", "expired", "missing"]),
469
+ /**
470
+ * Whether this integration is the primary system of record for its domain
471
+ * (e.g. HubSpot is SoR for contacts). Defaults to false.
472
+ */
473
+ isSystemOfRecord: z.boolean().default(false)
474
+ });
475
+ DisplayMetadataSchema.extend({
476
+ id: ModelIdSchema,
477
+ resourceId: z.string().trim().min(1).max(255),
478
+ resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
479
+ systemIds: ReferenceIdsSchema,
480
+ entityIds: ReferenceIdsSchema,
481
+ surfaceIds: ReferenceIdsSchema,
482
+ actionIds: ReferenceIdsSchema,
483
+ /** Optional tech-stack metadata for external-SaaS integrations. */
484
+ techStack: TechStackEntrySchema.optional()
485
+ });
486
+ var EntityIdSchema = ModelIdSchema;
487
+ var EntityLinkKindSchema = z.enum(["belongs-to", "has-many", "has-one", "many-to-many"]).meta({ label: "Link kind" });
488
+ var EntityLinkSchema = z.object({
489
+ toEntity: EntityIdSchema.meta({ ref: "entity" }),
490
+ kind: EntityLinkKindSchema,
491
+ via: z.string().trim().min(1).max(255).optional(),
492
+ label: LabelSchema.optional()
493
+ });
494
+ var EntitySchema = z.object({
495
+ id: EntityIdSchema,
496
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
497
+ order: z.number(),
498
+ label: LabelSchema,
499
+ description: DescriptionSchema.optional(),
500
+ ownedBySystemId: ModelIdSchema.meta({ ref: "system" }),
501
+ table: z.string().trim().min(1).max(255).optional(),
502
+ rowSchema: ModelIdSchema.optional(),
503
+ stateCatalogId: ModelIdSchema.optional(),
504
+ links: z.array(EntityLinkSchema).optional()
505
+ });
506
+ z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
507
+ message: "Each entity entry id must match its map key"
508
+ }).default({});
509
+
510
+ // ../core/src/organization-model/domains/actions.ts
511
+ var ActionResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
512
+ z.enum(["slash-command", "mcp-tool", "api-endpoint", "script-execution"]).meta({ label: "Invocation kind" });
513
+ var ActionIdSchema = ModelIdSchema;
514
+ var ActionScopeSchema = z.union([
515
+ z.literal("global"),
516
+ z.object({
517
+ domain: ModelIdSchema
518
+ })
519
+ ]);
520
+ var ActionRefSchema = z.object({
521
+ actionId: ActionIdSchema.meta({ ref: "action" }),
522
+ intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
523
+ });
524
+ var SlashCommandInvocationSchema = z.object({
525
+ kind: z.literal("slash-command"),
526
+ command: z.string().trim().min(1).max(200).regex(/^\/[^\s].*$/, "Slash commands must start with /"),
527
+ toolFactory: ModelIdSchema.optional()
528
+ });
529
+ var McpToolInvocationSchema = z.object({
530
+ kind: z.literal("mcp-tool"),
531
+ server: ModelIdSchema,
532
+ name: ModelIdSchema
533
+ });
534
+ var ApiEndpointInvocationSchema = z.object({
535
+ kind: z.literal("api-endpoint"),
536
+ method: z.enum(["GET", "POST", "PATCH", "DELETE"]).meta({ label: "HTTP method" }),
537
+ path: z.string().trim().startsWith("/").max(500),
538
+ requestSchema: ModelIdSchema.optional(),
539
+ responseSchema: ModelIdSchema.optional()
540
+ });
541
+ var ScriptExecutionInvocationSchema = z.object({
542
+ kind: z.literal("script-execution"),
543
+ resourceId: ActionResourceIdSchema
544
+ });
545
+ var ActionInvocationSchema = z.discriminatedUnion("kind", [
546
+ SlashCommandInvocationSchema,
547
+ McpToolInvocationSchema,
548
+ ApiEndpointInvocationSchema,
549
+ ScriptExecutionInvocationSchema
550
+ ]);
551
+ var ActionSchema = z.object({
552
+ id: ActionIdSchema,
553
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
554
+ order: z.number(),
555
+ label: LabelSchema,
556
+ description: DescriptionSchema.optional(),
557
+ scope: ActionScopeSchema.default("global"),
558
+ resourceId: ActionResourceIdSchema.optional(),
559
+ affects: z.array(EntityIdSchema.meta({ ref: "entity" })).optional(),
560
+ invocations: z.array(ActionInvocationSchema).default([]),
561
+ knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
562
+ lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
563
+ });
564
+ z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
565
+ message: "Each action entry id must match its map key"
566
+ }).default({});
567
+
920
568
  // ../core/src/organization-model/domains/systems.ts
921
569
  var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
922
570
  var SystemLifecycleSchema = z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
@@ -927,7 +575,7 @@ var SystemPathSchema = z.string().trim().min(1).regex(
927
575
  'must be a dotted lowercase path (e.g. "sales.lead-gen" or "sales.crm")'
928
576
  );
929
577
  var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]).meta({ label: "UI position" });
930
- var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(
578
+ z.string().trim().min(1).max(200).regex(
931
579
  /^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
932
580
  "Node references must use kind:dotted-path (e.g. system:sales.crm or resource:lead-gen.company.qualify)"
933
581
  );
@@ -1022,10 +670,9 @@ var SystemEntrySchema = z.object({
1022
670
  console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
1023
671
  return normalizedSystem.lifecycle === void 0 ? { ...normalizedSystem, lifecycle: normalizedSystem.status } : normalizedSystem;
1024
672
  });
1025
- var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
673
+ z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1026
674
  message: "Each system entry id must match its map key"
1027
675
  }).default({});
1028
- var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {};
1029
676
 
1030
677
  // ../core/src/organization-model/domains/resources.ts
1031
678
  var ContractRefSchema = z.string().trim().min(1).max(500).regex(
@@ -1164,10 +811,9 @@ var ResourceEntrySchema = z.discriminatedUnion("kind", [
1164
811
  IntegrationResourceEntrySchema,
1165
812
  ScriptResourceEntrySchema
1166
813
  ]);
1167
- var ResourcesDomainSchema = z.record(z.string(), ResourceEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
814
+ z.record(z.string(), ResourceEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1168
815
  message: "Each resource entry id must match its map key"
1169
816
  }).default({});
1170
- var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {};
1171
817
  function defineResource(resource) {
1172
818
  return ResourceEntrySchema.parse(resource);
1173
819
  }
@@ -1192,192 +838,6 @@ function defineResourceOntology(input) {
1192
838
  emits: ontologyIdArrayFrom(input.emits)
1193
839
  });
1194
840
  }
1195
-
1196
- // ../core/src/organization-model/domains/roles.ts
1197
- var RoleIdSchema = ModelIdSchema;
1198
- var HumanRoleHolderSchema = z.object({
1199
- kind: z.literal("human"),
1200
- userId: z.string().trim().min(1).max(200)
1201
- });
1202
- var AgentRoleHolderSchema = z.object({
1203
- kind: z.literal("agent"),
1204
- agentId: ResourceIdSchema.meta({ ref: "resource" })
1205
- });
1206
- var TeamRoleHolderSchema = z.object({
1207
- kind: z.literal("team"),
1208
- memberIds: z.array(z.string().trim().min(1).max(200)).min(1)
1209
- });
1210
- var RoleHolderSchema = z.discriminatedUnion("kind", [
1211
- HumanRoleHolderSchema,
1212
- AgentRoleHolderSchema,
1213
- TeamRoleHolderSchema
1214
- ]);
1215
- var RoleHoldersSchema = z.union([RoleHolderSchema, z.array(RoleHolderSchema).min(1)]);
1216
- var RoleSchema = z.object({
1217
- /** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
1218
- id: RoleIdSchema,
1219
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1220
- order: z.number(),
1221
- /** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
1222
- title: z.string().trim().min(1).max(200),
1223
- /**
1224
- * List of responsibilities this role owns - plain-language descriptions of
1225
- * what the person in this role is accountable for delivering.
1226
- * Defaults to empty array so minimal role definitions stay concise.
1227
- */
1228
- responsibilities: z.array(z.string().trim().max(500)).default([]),
1229
- /**
1230
- * Optional: ID of another role this role reports to.
1231
- * When present, must reference another `roles[].id` in the same organization.
1232
- */
1233
- reportsToId: RoleIdSchema.meta({ ref: "role" }).optional(),
1234
- /**
1235
- * Optional: human, agent, or team holder currently filling this role.
1236
- * Agent holders reference OM Resource IDs and are validated at the model level.
1237
- */
1238
- heldBy: RoleHoldersSchema.optional(),
1239
- /**
1240
- * Optional Systems this role is accountable for.
1241
- * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
1242
- */
1243
- responsibleFor: z.array(SystemIdSchema.meta({ ref: "system" })).optional()
1244
- });
1245
- var RolesDomainSchema = z.record(z.string(), RoleSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1246
- message: "Each role entry id must match its map key"
1247
- }).default({});
1248
- var DEFAULT_ORGANIZATION_MODEL_ROLES = {};
1249
- var KeyResultSchema = z.object({
1250
- /** Stable unique identifier for the measurable outcome (e.g. "kr-revenue-q1"). */
1251
- id: z.string().trim().min(1).max(100),
1252
- /** Plain-language description of this measurable outcome (e.g. "Increase trial-to-paid conversion"). */
1253
- description: z.string().trim().min(1).max(500),
1254
- /**
1255
- * What is being measured — the metric name (e.g. "monthly revenue", "NPS score",
1256
- * "trial-to-paid conversion rate"). Free-form string.
1257
- */
1258
- targetMetric: z.string().trim().min(1).max(200),
1259
- /** Current measured value. Defaults to 0 when not yet tracked. */
1260
- currentValue: z.number().default(0),
1261
- /**
1262
- * Target value to reach for this measurable outcome to be considered achieved.
1263
- * Optional — omit if the outcome is directional (e.g. "reduce churn") without
1264
- * a hard numeric target.
1265
- */
1266
- targetValue: z.number().optional()
1267
- });
1268
- var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
1269
- var ObjectiveSchema = z.object({
1270
- /** Stable unique identifier for the goal (e.g. "goal-grow-arr-q1-2026"). */
1271
- id: z.string().trim().min(1).max(100),
1272
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1273
- order: z.number(),
1274
- /** Plain-language description of what the organization wants to achieve. */
1275
- description: z.string().trim().min(1).max(1e3),
1276
- /**
1277
- * Start of the period this goal is active for — ISO 8601 date string (YYYY-MM-DD).
1278
- * Must be strictly before `periodEnd`.
1279
- */
1280
- periodStart: z.string().regex(ISO_DATE_REGEX, "periodStart must be an ISO date string (YYYY-MM-DD)"),
1281
- /**
1282
- * End of the period this goal is active for — ISO 8601 date string (YYYY-MM-DD).
1283
- * Must be strictly after `periodStart`.
1284
- * Enforced via `OrganizationModelSchema.superRefine()`.
1285
- */
1286
- periodEnd: z.string().regex(ISO_DATE_REGEX, "periodEnd must be an ISO date string (YYYY-MM-DD)"),
1287
- /**
1288
- * List of measurable outcomes that define success for this goal.
1289
- * Defaults to empty array so goals can be declared before outcomes are defined.
1290
- */
1291
- keyResults: z.array(KeyResultSchema).default([])
1292
- });
1293
- var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1294
- message: "Each objective entry id must match its map key"
1295
- }).default({});
1296
- var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
1297
- var KnowledgeTargetKindSchema = z.enum([
1298
- "system",
1299
- "resource",
1300
- "knowledge",
1301
- "stage",
1302
- "action",
1303
- "role",
1304
- "goal",
1305
- "customer-segment",
1306
- "offering",
1307
- "ontology"
1308
- ]).meta({ label: "Target kind" });
1309
- var KnowledgeTargetRefSchema = z.object({
1310
- kind: KnowledgeTargetKindSchema,
1311
- // Ontology targets use the canonical '<scope>:<kind>/<local-id>' ontology id format.
1312
- // Business-logic validation of target existence is done in OrganizationModelSchema.superRefine.
1313
- id: z.string().trim().min(1).max(300)
1314
- }).superRefine((target, ctx) => {
1315
- if (target.kind !== "ontology") return;
1316
- const result = OntologyIdSchema.safeParse(target.id);
1317
- if (!result.success) {
1318
- ctx.addIssue({
1319
- code: z.ZodIssueCode.custom,
1320
- path: ["id"],
1321
- message: "Ontology knowledge targets must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
1322
- });
1323
- }
1324
- });
1325
- var LegacyKnowledgeLinkSchema = z.object({
1326
- nodeId: z.union([NodeIdStringSchema, z.templateLiteral(["ontology:", OntologyIdSchema])])
1327
- }).superRefine((link, ctx) => {
1328
- const [kind] = link.nodeId.split(":");
1329
- if (!KnowledgeTargetKindSchema.safeParse(kind).success) {
1330
- ctx.addIssue({
1331
- code: z.ZodIssueCode.custom,
1332
- path: ["nodeId"],
1333
- message: `Unknown knowledge target kind "${kind}"`
1334
- });
1335
- }
1336
- });
1337
- var CanonicalKnowledgeLinkSchema = z.object({
1338
- target: KnowledgeTargetRefSchema
1339
- });
1340
- function nodeIdFromTarget(target) {
1341
- return `${target.kind}:${target.id}`;
1342
- }
1343
- function targetFromNodeId(nodeId) {
1344
- const [kind, ...idParts] = nodeId.split(":");
1345
- return {
1346
- kind: KnowledgeTargetKindSchema.parse(kind),
1347
- id: idParts.join(":")
1348
- };
1349
- }
1350
- var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
1351
- const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
1352
- return {
1353
- target,
1354
- nodeId: nodeIdFromTarget(target)
1355
- };
1356
- });
1357
- var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
1358
- var OrgKnowledgeNodeSchema = z.object({
1359
- id: ModelIdSchema,
1360
- kind: OrgKnowledgeKindSchema,
1361
- title: z.string().trim().min(1).max(200),
1362
- summary: z.string().trim().min(1).max(1e3),
1363
- icon: IconNameSchema.optional(),
1364
- /** Canonical documentation URL when body content is a local summary. */
1365
- externalUrl: z.string().trim().url().max(500).optional(),
1366
- /** Optional generated source file path for local MDX-backed knowledge nodes. */
1367
- sourceFilePath: z.string().trim().min(1).max(500).optional(),
1368
- /** Raw MDX string. Phase 2 will introduce a structured block format. */
1369
- body: z.string().trim().min(1),
1370
- /**
1371
- * Graph links to other OM nodes this knowledge node governs.
1372
- * Each link emits a `governs` edge: knowledge-node -> target node.
1373
- */
1374
- links: z.array(KnowledgeLinkSchema).default([]),
1375
- /** Role identifiers that own this knowledge node. */
1376
- ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
1377
- /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
1378
- updatedAt: z.string().trim().min(1).max(50)
1379
- });
1380
- var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
1381
841
  var SecretLikeMetadataKeySchema = /(?:secret|password|passwd|token|api[-_]?key|credential|private[-_]?key)/i;
1382
842
  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-----)/;
1383
843
  var OmTopologyNodeKindSchema = z.enum([
@@ -1441,10 +901,6 @@ var OmTopologyDomainSchema = z.object({
1441
901
  version: z.literal(1).default(1),
1442
902
  relationships: z.record(z.string().trim().min(1).max(255), OmTopologyRelationshipSchema).default({})
1443
903
  }).default({ version: 1, relationships: {} });
1444
- var DEFAULT_ORGANIZATION_MODEL_TOPOLOGY = {
1445
- version: 1,
1446
- relationships: {}
1447
- };
1448
904
  function idFrom(input) {
1449
905
  return typeof input === "string" ? input : input.id;
1450
906
  }
@@ -1521,807 +977,26 @@ function parseTopologyNodeRef(input) {
1521
977
  if (separatorIndex === -1) {
1522
978
  throw new Error(`Topology node ref "${input}" must use <kind>:<id>`);
1523
979
  }
1524
- const kind = input.slice(0, separatorIndex);
1525
- const id = input.slice(separatorIndex + 1);
1526
- if (!OmTopologyNodeKindSchema.safeParse(kind).success) {
1527
- throw new Error(`Topology node ref "${input}" has unsupported kind "${kind}"`);
1528
- }
1529
- return OmTopologyNodeRefSchema.parse({ kind, id });
1530
- }
1531
- function defineTopologyRelationship(input) {
1532
- return OmTopologyRelationshipSchema.parse({
1533
- ...input,
1534
- from: compileTopologyNodeRef(input.from),
1535
- to: compileTopologyNodeRef(input.to)
1536
- });
1537
- }
1538
- function defineTopology(relationships) {
1539
- const entries = Array.isArray(relationships) ? relationships.map((relationship, index) => [`relationship-${index + 1}`, relationship]) : Object.entries(relationships);
1540
- return OmTopologyDomainSchema.parse({
1541
- version: 1,
1542
- relationships: Object.fromEntries(entries.map(([key, relationship]) => [key, defineTopologyRelationship(relationship)]))
1543
- });
1544
- }
1545
- var PolicyIdSchema = ModelIdSchema;
1546
- var PolicyApplicabilitySchema = z.object({
1547
- systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
1548
- actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
1549
- resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
1550
- roleIds: z.array(ModelIdSchema.meta({ ref: "role" })).default([])
1551
- });
1552
- var PolicyTriggerSchema = z.discriminatedUnion("kind", [
1553
- z.object({
1554
- kind: z.literal("event"),
1555
- eventId: EventIdSchema.meta({ ref: "event" })
1556
- }),
1557
- z.object({
1558
- kind: z.literal("action-invocation"),
1559
- actionId: ModelIdSchema.meta({ ref: "action" })
1560
- }),
1561
- z.object({
1562
- kind: z.literal("schedule"),
1563
- cron: z.string().trim().min(1).max(120)
1564
- }),
1565
- z.object({
1566
- kind: z.literal("manual")
1567
- })
1568
- ]);
1569
- var PolicyPredicateSchema = z.discriminatedUnion("kind", [
1570
- z.object({
1571
- kind: z.literal("always")
1572
- }),
1573
- z.object({
1574
- kind: z.literal("expression"),
1575
- expression: z.string().trim().min(1).max(2e3)
1576
- }),
1577
- z.object({
1578
- kind: z.literal("threshold"),
1579
- metric: ModelIdSchema,
1580
- operator: z.enum(["lt", "lte", "eq", "gte", "gt"]).meta({ label: "Operator" }),
1581
- value: z.number()
1582
- })
1583
- ]);
1584
- var PolicyEffectSchema = z.discriminatedUnion("kind", [
1585
- z.object({
1586
- kind: z.literal("require-approval"),
1587
- roleId: ModelIdSchema.meta({ ref: "role" }).optional()
1588
- }),
1589
- z.object({
1590
- kind: z.literal("invoke-action"),
1591
- actionId: ModelIdSchema.meta({ ref: "action" })
1592
- }),
1593
- z.object({
1594
- kind: z.literal("notify-role"),
1595
- roleId: ModelIdSchema.meta({ ref: "role" })
1596
- }),
1597
- z.object({
1598
- kind: z.literal("block")
1599
- })
1600
- ]);
1601
- var PolicySchema = z.object({
1602
- id: PolicyIdSchema,
1603
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1604
- order: z.number(),
1605
- label: LabelSchema,
1606
- description: DescriptionSchema.optional(),
1607
- trigger: PolicyTriggerSchema,
1608
- predicate: PolicyPredicateSchema.default({ kind: "always" }),
1609
- actions: z.array(PolicyEffectSchema).min(1),
1610
- appliesTo: PolicyApplicabilitySchema.default({
1611
- systemIds: [],
1612
- actionIds: [],
1613
- resourceIds: [],
1614
- roleIds: []
1615
- }),
1616
- lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
1617
- });
1618
- var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1619
- message: "Each policy entry id must match its map key"
1620
- }).default({});
1621
- var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
1622
-
1623
- // ../core/src/organization-model/schema.ts
1624
- z.enum([
1625
- "branding",
1626
- "identity",
1627
- "customers",
1628
- "offerings",
1629
- "roles",
1630
- "goals",
1631
- "systems",
1632
- "ontology",
1633
- "resources",
1634
- "topology",
1635
- "actions",
1636
- "entities",
1637
- "policies",
1638
- "knowledge"
1639
- ]);
1640
- var OrganizationModelDomainMetadataSchema = z.object({
1641
- version: z.literal(1).default(1),
1642
- lastModified: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "lastModified must be an ISO date string (YYYY-MM-DD)")
1643
- });
1644
- var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
1645
- branding: { version: 1, lastModified: "2026-05-10" },
1646
- identity: { version: 1, lastModified: "2026-05-10" },
1647
- customers: { version: 1, lastModified: "2026-05-10" },
1648
- offerings: { version: 1, lastModified: "2026-05-10" },
1649
- roles: { version: 1, lastModified: "2026-05-10" },
1650
- goals: { version: 1, lastModified: "2026-05-10" },
1651
- systems: { version: 1, lastModified: "2026-05-10" },
1652
- ontology: { version: 1, lastModified: "2026-05-14" },
1653
- resources: { version: 1, lastModified: "2026-05-10" },
1654
- topology: { version: 1, lastModified: "2026-05-14" },
1655
- actions: { version: 1, lastModified: "2026-05-10" },
1656
- entities: { version: 1, lastModified: "2026-05-10" },
1657
- policies: { version: 1, lastModified: "2026-05-10" },
1658
- knowledge: { version: 1, lastModified: "2026-05-10" }
1659
- };
1660
- var OrganizationModelDomainMetadataByDomainSchema = z.object({
1661
- branding: OrganizationModelDomainMetadataSchema,
1662
- identity: OrganizationModelDomainMetadataSchema,
1663
- customers: OrganizationModelDomainMetadataSchema,
1664
- offerings: OrganizationModelDomainMetadataSchema,
1665
- roles: OrganizationModelDomainMetadataSchema,
1666
- goals: OrganizationModelDomainMetadataSchema,
1667
- systems: OrganizationModelDomainMetadataSchema,
1668
- ontology: OrganizationModelDomainMetadataSchema,
1669
- resources: OrganizationModelDomainMetadataSchema,
1670
- topology: OrganizationModelDomainMetadataSchema,
1671
- actions: OrganizationModelDomainMetadataSchema,
1672
- entities: OrganizationModelDomainMetadataSchema,
1673
- policies: OrganizationModelDomainMetadataSchema,
1674
- knowledge: OrganizationModelDomainMetadataSchema
1675
- }).partial().default(DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA).transform((metadata) => ({ ...DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, ...metadata }));
1676
- var OrganizationModelSchemaBase = z.object({
1677
- version: z.literal(1).default(1),
1678
- domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
1679
- branding: OrganizationModelBrandingSchema,
1680
- navigation: OrganizationModelNavigationSchema,
1681
- identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
1682
- customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
1683
- offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
1684
- roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
1685
- goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
1686
- systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
1687
- ontology: OntologyScopeSchema.default(DEFAULT_ONTOLOGY_SCOPE),
1688
- resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
1689
- topology: OmTopologyDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_TOPOLOGY),
1690
- actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
1691
- entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
1692
- policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
1693
- // D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
1694
- knowledge: KnowledgeDomainSchema.default({})
1695
- });
1696
- function addIssue(ctx, path, message) {
1697
- ctx.addIssue({
1698
- code: z.ZodIssueCode.custom,
1699
- path,
1700
- message
1701
- });
1702
- }
1703
- function isLifecycleEnabled(lifecycle, enabled) {
1704
- if (enabled === false) return false;
1705
- return lifecycle !== "deprecated" && lifecycle !== "archived";
1706
- }
1707
- function defaultSystemPathFor(id) {
1708
- return `/${id.replaceAll(".", "/")}`;
1709
- }
1710
- function asRoleHolderArray(heldBy) {
1711
- return Array.isArray(heldBy) ? heldBy : [heldBy];
1712
- }
1713
- function isKnowledgeKindCompatibleWithTarget(knowledgeKind, targetKind) {
1714
- if (knowledgeKind === "reference") return true;
1715
- if (knowledgeKind === "playbook") {
1716
- return ["system", "resource", "stage", "action", "ontology"].includes(targetKind);
1717
- }
1718
- if (knowledgeKind === "strategy") {
1719
- return ["system", "goal", "offering", "customer-segment", "ontology"].includes(targetKind);
1720
- }
1721
- return false;
1722
- }
1723
- function isRecord(value) {
1724
- return typeof value === "object" && value !== null && !Array.isArray(value);
1725
- }
1726
- OrganizationModelSchemaBase.superRefine((model, ctx) => {
1727
- function collectAllSystems(systems, prefix = "", schemaPath = ["systems"]) {
1728
- const result = [];
1729
- for (const [key, system] of Object.entries(systems)) {
1730
- const path = prefix ? `${prefix}.${key}` : key;
1731
- const currentSchemaPath = [...schemaPath, key];
1732
- result.push({ path, schemaPath: currentSchemaPath, system });
1733
- const childSystems = system.systems ?? system.subsystems;
1734
- if (childSystems !== void 0) {
1735
- result.push(
1736
- ...collectAllSystems(childSystems, path, [
1737
- ...currentSchemaPath,
1738
- system.systems !== void 0 ? "systems" : "subsystems"
1739
- ])
1740
- );
1741
- }
1742
- }
1743
- return result;
1744
- }
1745
- const allSystems = collectAllSystems(model.systems);
1746
- const systemsById = /* @__PURE__ */ new Map();
1747
- for (const { path, system } of allSystems) {
1748
- systemsById.set(path, system);
1749
- systemsById.set(system.id, system);
1750
- }
1751
- const systemIdsByEffectivePath = /* @__PURE__ */ new Map();
1752
- allSystems.forEach(({ path, schemaPath, system }) => {
1753
- if (system.parentSystemId !== void 0 && !systemsById.has(system.parentSystemId)) {
1754
- addIssue(
1755
- ctx,
1756
- [...schemaPath, "parentSystemId"],
1757
- `System "${system.id}" references unknown parent "${system.parentSystemId}"`
1758
- );
1759
- }
1760
- const hasChildren = Object.keys(system.systems ?? system.subsystems ?? {}).length > 0 || allSystems.some(
1761
- (candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".")
1762
- );
1763
- const contributesRoutePath = system.ui?.path !== void 0 || system.path !== void 0 || !hasChildren;
1764
- if (contributesRoutePath) {
1765
- const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path);
1766
- const existingSystemId = systemIdsByEffectivePath.get(effectivePath);
1767
- if (existingSystemId !== void 0) {
1768
- addIssue(
1769
- ctx,
1770
- [...schemaPath, system.ui?.path !== void 0 ? "ui" : "path"],
1771
- `System "${path}" effective path "${effectivePath}" duplicates system "${existingSystemId}"`
1772
- );
1773
- } else {
1774
- systemIdsByEffectivePath.set(effectivePath, path);
1775
- }
1776
- }
1777
- if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
1778
- const hasEnabledDescendant = Object.values(system.systems ?? system.subsystems ?? {}).some(
1779
- (candidate) => isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
1780
- ) || allSystems.some(
1781
- (candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
1782
- );
1783
- if (!hasEnabledDescendant) {
1784
- addIssue(ctx, [...schemaPath, "lifecycle"], `System "${path}" is active but has no active descendants`);
1785
- }
1786
- }
1787
- });
1788
- allSystems.forEach(({ schemaPath, system }) => {
1789
- const visited = /* @__PURE__ */ new Set();
1790
- let currentParentId = system.parentSystemId;
1791
- while (currentParentId !== void 0) {
1792
- if (currentParentId === system.id || visited.has(currentParentId)) {
1793
- addIssue(ctx, [...schemaPath, "parentSystemId"], `System "${system.id}" has a parent cycle`);
1794
- return;
1795
- }
1796
- visited.add(currentParentId);
1797
- currentParentId = systemsById.get(currentParentId)?.parentSystemId;
1798
- }
1799
- });
1800
- function normalizeRoutePath(path) {
1801
- return path.length > 1 ? path.replace(/\/+$/, "") : path;
1802
- }
1803
- const sidebarNodeIds = /* @__PURE__ */ new Map();
1804
- const sidebarSurfacePaths = /* @__PURE__ */ new Map();
1805
- const sidebarSurfaces = [];
1806
- function collectSidebarNodes(nodes, schemaPath) {
1807
- Object.entries(nodes).forEach(([nodeId, node]) => {
1808
- const nodePath = [...schemaPath, nodeId];
1809
- const existingNodePath = sidebarNodeIds.get(nodeId);
1810
- if (existingNodePath !== void 0) {
1811
- addIssue(ctx, nodePath, `Sidebar node id "${nodeId}" duplicates another sidebar node`);
1812
- } else {
1813
- sidebarNodeIds.set(nodeId, nodePath);
1814
- }
1815
- if (node.type === "group") {
1816
- collectSidebarNodes(node.children, [...nodePath, "children"]);
1817
- return;
1818
- }
1819
- sidebarSurfaces.push({ id: nodeId, node, path: nodePath });
1820
- const normalizedPath = normalizeRoutePath(node.path);
1821
- const existingSurfaceId = sidebarSurfacePaths.get(normalizedPath);
1822
- if (existingSurfaceId !== void 0) {
1823
- addIssue(
1824
- ctx,
1825
- [...nodePath, "path"],
1826
- `Sidebar surface path "${node.path}" duplicates surface "${existingSurfaceId}"`
1827
- );
1828
- } else {
1829
- sidebarSurfacePaths.set(normalizedPath, nodeId);
1830
- }
1831
- node.targets?.systems?.forEach((systemId, systemIndex) => {
1832
- if (!systemsById.has(systemId)) {
1833
- addIssue(
1834
- ctx,
1835
- [...nodePath, "targets", "systems", systemIndex],
1836
- `Sidebar surface "${nodeId}" references unknown system "${systemId}"`
1837
- );
1838
- }
1839
- });
1840
- });
1841
- }
1842
- collectSidebarNodes(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]);
1843
- collectSidebarNodes(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"]);
1844
- const segmentsById = new Map(Object.entries(model.customers));
1845
- Object.values(model.offerings).forEach((product) => {
1846
- product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
1847
- if (!segmentsById.has(segmentId)) {
1848
- addIssue(
1849
- ctx,
1850
- ["offerings", product.id, "targetSegmentIds", segmentIndex],
1851
- `Product "${product.id}" references unknown customer segment "${segmentId}"`
1852
- );
1853
- }
1854
- });
1855
- if (product.deliveryFeatureId !== void 0 && !systemsById.has(product.deliveryFeatureId)) {
1856
- addIssue(
1857
- ctx,
1858
- ["offerings", product.id, "deliveryFeatureId"],
1859
- `Product "${product.id}" references unknown delivery system "${product.deliveryFeatureId}"`
1860
- );
1861
- }
1862
- });
1863
- Object.values(model.goals).forEach((objective) => {
1864
- if (objective.periodEnd <= objective.periodStart) {
1865
- addIssue(
1866
- ctx,
1867
- ["goals", objective.id, "periodEnd"],
1868
- `Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
1869
- );
1870
- }
1871
- });
1872
- const goalsById = new Map(Object.entries(model.goals));
1873
- const knowledgeById = new Map(Object.entries(model.knowledge));
1874
- const actionsById = new Map(Object.entries(model.actions));
1875
- const entitiesById = new Map(Object.entries(model.entities));
1876
- const policiesById = new Map(Object.entries(model.policies));
1877
- sidebarSurfaces.forEach(({ id, node, path }) => {
1878
- node.targets?.entities?.forEach((entityId, entityIndex) => {
1879
- if (!entitiesById.has(entityId)) {
1880
- addIssue(
1881
- ctx,
1882
- [...path, "targets", "entities", entityIndex],
1883
- `Sidebar surface "${id}" references unknown entity "${entityId}"`
1884
- );
1885
- }
1886
- });
1887
- node.targets?.actions?.forEach((actionId, actionIndex) => {
1888
- if (!actionsById.has(actionId)) {
1889
- addIssue(
1890
- ctx,
1891
- [...path, "targets", "actions", actionIndex],
1892
- `Sidebar surface "${id}" references unknown action "${actionId}"`
1893
- );
1894
- }
1895
- });
1896
- });
1897
- Object.values(model.entities).forEach((entity) => {
1898
- if (!systemsById.has(entity.ownedBySystemId)) {
1899
- addIssue(
1900
- ctx,
1901
- ["entities", entity.id, "ownedBySystemId"],
1902
- `Entity "${entity.id}" references unknown ownedBySystemId "${entity.ownedBySystemId}"`
1903
- );
1904
- }
1905
- entity.links?.forEach((link, linkIndex) => {
1906
- if (!entitiesById.has(link.toEntity)) {
1907
- addIssue(
1908
- ctx,
1909
- ["entities", entity.id, "links", linkIndex, "toEntity"],
1910
- `Entity "${entity.id}" links to unknown entity "${link.toEntity}"`
1911
- );
1912
- }
1913
- });
1914
- });
1915
- const rolesById = new Map(Object.entries(model.roles));
1916
- Object.values(model.roles).forEach((role) => {
1917
- if (role.reportsToId !== void 0 && !rolesById.has(role.reportsToId)) {
1918
- addIssue(
1919
- ctx,
1920
- ["roles", role.id, "reportsToId"],
1921
- `Role "${role.id}" references unknown reportsToId "${role.reportsToId}"`
1922
- );
1923
- }
1924
- });
1925
- Object.values(model.roles).forEach((role) => {
1926
- const visited = /* @__PURE__ */ new Set();
1927
- let currentReportsToId = role.reportsToId;
1928
- while (currentReportsToId !== void 0) {
1929
- if (currentReportsToId === role.id || visited.has(currentReportsToId)) {
1930
- addIssue(ctx, ["roles", role.id, "reportsToId"], `Role "${role.id}" has a reportsToId cycle`);
1931
- return;
1932
- }
1933
- visited.add(currentReportsToId);
1934
- currentReportsToId = rolesById.get(currentReportsToId)?.reportsToId;
1935
- }
1936
- });
1937
- Object.values(model.roles).forEach((role) => {
1938
- role.responsibleFor?.forEach((systemId, systemIndex) => {
1939
- if (!systemsById.has(systemId)) {
1940
- addIssue(
1941
- ctx,
1942
- ["roles", role.id, "responsibleFor", systemIndex],
1943
- `Role "${role.id}" references unknown responsibleFor system "${systemId}"`
1944
- );
1945
- }
1946
- });
1947
- });
1948
- allSystems.forEach(({ schemaPath, system }) => {
1949
- if (system.responsibleRoleId !== void 0 && !rolesById.has(system.responsibleRoleId)) {
1950
- addIssue(
1951
- ctx,
1952
- [...schemaPath, "responsibleRoleId"],
1953
- `System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
1954
- );
1955
- }
1956
- system.governedByKnowledge?.forEach((nodeId, nodeIndex) => {
1957
- if (!knowledgeById.has(nodeId)) {
1958
- addIssue(
1959
- ctx,
1960
- [...schemaPath, "governedByKnowledge", nodeIndex],
1961
- `System "${system.id}" references unknown knowledge node "${nodeId}"`
1962
- );
1963
- }
1964
- });
1965
- system.drivesGoals?.forEach((goalId, goalIndex) => {
1966
- if (!goalsById.has(goalId)) {
1967
- addIssue(
1968
- ctx,
1969
- [...schemaPath, "drivesGoals", goalIndex],
1970
- `System "${system.id}" references unknown goal "${goalId}"`
1971
- );
1972
- }
1973
- });
1974
- system.actions?.forEach((actionRef, actionIndex) => {
1975
- if (!actionsById.has(actionRef.actionId)) {
1976
- addIssue(
1977
- ctx,
1978
- [...schemaPath, "actions", actionIndex, "actionId"],
1979
- `System "${system.id}" references unknown action "${actionRef.actionId}"`
1980
- );
1981
- }
1982
- });
1983
- system.policies?.forEach((policyId, policyIndex) => {
1984
- if (!policiesById.has(policyId)) {
1985
- addIssue(
1986
- ctx,
1987
- [...schemaPath, "policies", policyIndex],
1988
- `System "${system.id}" references unknown policy "${policyId}"`
1989
- );
1990
- }
1991
- });
1992
- });
1993
- Object.values(model.actions).forEach((action) => {
1994
- action.affects?.forEach((entityId, entityIndex) => {
1995
- if (!entitiesById.has(entityId)) {
1996
- addIssue(
1997
- ctx,
1998
- ["actions", action.id, "affects", entityIndex],
1999
- `Action "${action.id}" affects unknown entity "${entityId}"`
2000
- );
2001
- }
2002
- });
2003
- });
2004
- const resourcesById = new Map(Object.entries(model.resources));
2005
- sidebarSurfaces.forEach(({ id, node, path }) => {
2006
- node.targets?.resources?.forEach((resourceId, resourceIndex) => {
2007
- if (!resourcesById.has(resourceId)) {
2008
- addIssue(
2009
- ctx,
2010
- [...path, "targets", "resources", resourceIndex],
2011
- `Sidebar surface "${id}" references unknown resource "${resourceId}"`
2012
- );
2013
- }
2014
- });
2015
- });
2016
- const actionIds = new Set(Object.keys(model.actions));
2017
- const offeringsById = new Map(Object.entries(model.offerings));
2018
- const ontologyCompilation = compileOrganizationOntology(model);
2019
- const stageIds = /* @__PURE__ */ new Set();
2020
- for (const catalog of Object.values(ontologyCompilation.ontology.catalogTypes)) {
2021
- if (catalog.kind !== "stage") continue;
2022
- for (const stageId of Object.keys(catalog.entries ?? {})) {
2023
- stageIds.add(stageId);
2024
- }
2025
- }
2026
- const ontologyIndexByKind = {
2027
- object: ontologyCompilation.ontology.objectTypes,
2028
- link: ontologyCompilation.ontology.linkTypes,
2029
- action: ontologyCompilation.ontology.actionTypes,
2030
- catalog: ontologyCompilation.ontology.catalogTypes,
2031
- event: ontologyCompilation.ontology.eventTypes,
2032
- interface: ontologyCompilation.ontology.interfaceTypes,
2033
- "value-type": ontologyCompilation.ontology.valueTypes,
2034
- property: ontologyCompilation.ontology.sharedProperties,
2035
- group: ontologyCompilation.ontology.groups,
2036
- surface: ontologyCompilation.ontology.surfaces
2037
- };
2038
- const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)));
2039
- function topologyTargetExists(ref) {
2040
- if (ref.kind === "system") return systemsById.has(ref.id);
2041
- if (ref.kind === "resource") return resourcesById.has(ref.id);
2042
- if (ref.kind === "ontology") return ontologyIds.has(ref.id);
2043
- if (ref.kind === "policy") return policiesById.has(ref.id);
2044
- if (ref.kind === "role") return rolesById.has(ref.id);
2045
- return true;
2046
- }
2047
- Object.entries(model.topology.relationships).forEach(([relationshipId, relationship]) => {
2048
- ["from", "to"].forEach((side) => {
2049
- const ref = relationship[side];
2050
- if (topologyTargetExists(ref)) return;
2051
- addIssue(
2052
- ctx,
2053
- ["topology", "relationships", relationshipId, side],
2054
- `Topology relationship "${relationshipId}" ${side} references unknown ${ref.kind} "${ref.id}"`
2055
- );
2056
- });
2057
- });
2058
- const ontologyReferenceKeyKinds = {
2059
- valueType: "value-type",
2060
- catalogType: "catalog",
2061
- objectType: "object",
2062
- eventType: "event",
2063
- actionType: "action",
2064
- linkType: "link",
2065
- interfaceType: "interface",
2066
- propertyType: "property",
2067
- groupType: "group",
2068
- surfaceType: "surface",
2069
- stepCatalog: "catalog"
2070
- };
2071
- function validateKnownOntologyReferences(ownerId, value, path, seen = /* @__PURE__ */ new WeakSet()) {
2072
- if (Array.isArray(value)) {
2073
- value.forEach((entry, index) => validateKnownOntologyReferences(ownerId, entry, [...path, index], seen));
2074
- return;
2075
- }
2076
- if (!isRecord(value)) return;
2077
- if (seen.has(value)) return;
2078
- seen.add(value);
2079
- Object.entries(value).forEach(([key, entry]) => {
2080
- const expectedKind = ontologyReferenceKeyKinds[key];
2081
- if (expectedKind !== void 0) {
2082
- if (typeof entry !== "string") {
2083
- addIssue(ctx, [...path, key], `Ontology record "${ownerId}" ${key} must be an ontology ID string`);
2084
- } else if (ontologyIndexByKind[expectedKind][entry] === void 0) {
2085
- addIssue(
2086
- ctx,
2087
- [...path, key],
2088
- `Ontology record "${ownerId}" ${key} references unknown ${expectedKind} ontology ID "${entry}"`
2089
- );
2090
- }
2091
- }
2092
- validateKnownOntologyReferences(ownerId, entry, [...path, key], seen);
2093
- });
2094
- }
2095
- for (const { id, record } of listResolvedOntologyRecords(ontologyCompilation.ontology)) {
2096
- validateKnownOntologyReferences(id, record, record.origin.path);
2097
- }
2098
- Object.values(model.policies).forEach((policy) => {
2099
- policy.appliesTo.systemIds.forEach((systemId, systemIndex) => {
2100
- if (!systemsById.has(systemId)) {
2101
- addIssue(
2102
- ctx,
2103
- ["policies", policy.id, "appliesTo", "systemIds", systemIndex],
2104
- `Policy "${policy.id}" applies to unknown system "${systemId}"`
2105
- );
2106
- }
2107
- });
2108
- policy.appliesTo.actionIds.forEach((actionId, actionIndex) => {
2109
- if (!actionsById.has(actionId)) {
2110
- addIssue(
2111
- ctx,
2112
- ["policies", policy.id, "appliesTo", "actionIds", actionIndex],
2113
- `Policy "${policy.id}" applies to unknown action "${actionId}"`
2114
- );
2115
- }
2116
- });
2117
- policy.actions.forEach((action, actionIndex) => {
2118
- if (action.kind === "invoke-action" && !actionsById.has(action.actionId)) {
2119
- addIssue(
2120
- ctx,
2121
- ["policies", policy.id, "actions", actionIndex, "actionId"],
2122
- `Policy "${policy.id}" invokes unknown action "${action.actionId}"`
2123
- );
2124
- }
2125
- if ((action.kind === "notify-role" || action.kind === "require-approval") && action.roleId !== void 0 && !rolesById.has(action.roleId)) {
2126
- addIssue(
2127
- ctx,
2128
- ["policies", policy.id, "actions", actionIndex, "roleId"],
2129
- `Policy "${policy.id}" references unknown role "${action.roleId}"`
2130
- );
2131
- }
2132
- });
2133
- if (policy.trigger.kind === "action-invocation" && !actionsById.has(policy.trigger.actionId)) {
2134
- addIssue(
2135
- ctx,
2136
- ["policies", policy.id, "trigger", "actionId"],
2137
- `Policy "${policy.id}" references unknown trigger action "${policy.trigger.actionId}"`
2138
- );
2139
- }
2140
- });
2141
- function knowledgeTargetExists(kind, id) {
2142
- if (kind === "system") return systemsById.has(id);
2143
- if (kind === "resource") return resourcesById.has(id);
2144
- if (kind === "knowledge") return knowledgeById.has(id);
2145
- if (kind === "stage") return stageIds.has(id);
2146
- if (kind === "action") return actionIds.has(id);
2147
- if (kind === "role") return rolesById.has(id);
2148
- if (kind === "goal") return goalsById.has(id);
2149
- if (kind === "customer-segment") return segmentsById.has(id);
2150
- if (kind === "offering") return offeringsById.has(id);
2151
- if (kind === "ontology") return ontologyIds.has(id);
2152
- return false;
2153
- }
2154
- Object.entries(model.knowledge).forEach(([nodeId, node]) => {
2155
- node.links.forEach((link, linkIndex) => {
2156
- if (!knowledgeTargetExists(link.target.kind, link.target.id)) {
2157
- addIssue(
2158
- ctx,
2159
- ["knowledge", nodeId, "links", linkIndex, "target"],
2160
- `Knowledge node "${node.id}" references unknown ${link.target.kind} target "${link.target.id}"`
2161
- );
2162
- }
2163
- if (!isKnowledgeKindCompatibleWithTarget(node.kind, link.target.kind)) {
2164
- addIssue(
2165
- ctx,
2166
- ["knowledge", nodeId, "links", linkIndex, "target", "kind"],
2167
- `Knowledge node "${node.id}" kind "${node.kind}" cannot govern ${link.target.kind} targets`
2168
- );
2169
- }
2170
- });
2171
- });
2172
- Object.values(model.resources).forEach((resource) => {
2173
- if (!systemsById.has(resource.systemPath)) {
2174
- addIssue(
2175
- ctx,
2176
- ["resources", resource.id, "systemPath"],
2177
- `Resource "${resource.id}" references unknown system path "${resource.systemPath}"`
2178
- );
2179
- }
2180
- if (resource.ownerRoleId !== void 0 && !rolesById.has(resource.ownerRoleId)) {
2181
- addIssue(
2182
- ctx,
2183
- ["resources", resource.id, "ownerRoleId"],
2184
- `Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
2185
- );
2186
- }
2187
- if (resource.kind === "agent" && resource.actsAsRoleId !== void 0 && !rolesById.has(resource.actsAsRoleId)) {
2188
- addIssue(
2189
- ctx,
2190
- ["resources", resource.id, "actsAsRoleId"],
2191
- `Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
2192
- );
2193
- }
2194
- });
2195
- function validateResourceOntologyBinding(resourceId, bindingKey, expectedKind, ids) {
2196
- const ontologyIds2 = ids === void 0 ? [] : Array.isArray(ids) ? ids : [ids];
2197
- ontologyIds2.forEach((ontologyId, ontologyIndex) => {
2198
- if (ontologyIndexByKind[expectedKind][ontologyId] === void 0) {
2199
- addIssue(
2200
- ctx,
2201
- ["resources", resourceId, "ontology", bindingKey, ...Array.isArray(ids) ? [ontologyIndex] : []],
2202
- `Resource "${resourceId}" ontology binding "${bindingKey}" references unknown ${expectedKind} ontology ID "${ontologyId}"`
2203
- );
2204
- }
2205
- });
980
+ const kind = input.slice(0, separatorIndex);
981
+ const id = input.slice(separatorIndex + 1);
982
+ if (!OmTopologyNodeKindSchema.safeParse(kind).success) {
983
+ throw new Error(`Topology node ref "${input}" has unsupported kind "${kind}"`);
2206
984
  }
2207
- Object.values(model.resources).forEach((resource) => {
2208
- const binding = resource.ontology;
2209
- if (binding === void 0) return;
2210
- validateResourceOntologyBinding(resource.id, "actions", "action", binding.actions);
2211
- validateResourceOntologyBinding(resource.id, "primaryAction", "action", binding.primaryAction);
2212
- validateResourceOntologyBinding(resource.id, "reads", "object", binding.reads);
2213
- validateResourceOntologyBinding(resource.id, "writes", "object", binding.writes);
2214
- validateResourceOntologyBinding(resource.id, "usesCatalogs", "catalog", binding.usesCatalogs);
2215
- validateResourceOntologyBinding(resource.id, "emits", "event", binding.emits);
2216
- if (binding.contract !== void 0) {
2217
- const contractEntries = [
2218
- ["input", binding.contract.input],
2219
- ["output", binding.contract.output]
2220
- ];
2221
- for (const [side, ref] of contractEntries) {
2222
- if (ref === void 0) continue;
2223
- const result = ContractRefSchema.safeParse(ref);
2224
- if (!result.success) {
2225
- addIssue(
2226
- ctx,
2227
- ["resources", resource.id, "ontology", "contract", side],
2228
- `Resource "${resource.id}" contract.${side} "${ref}" is not a valid ContractRef (expected "package/subpath#ExportName")`
2229
- );
2230
- }
2231
- }
2232
- }
2233
- });
2234
- Object.values(model.roles).forEach((role) => {
2235
- if (role.heldBy === void 0) return;
2236
- asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
2237
- if (holder.kind !== "agent") return;
2238
- const resource = resourcesById.get(holder.agentId);
2239
- if (resource === void 0) {
2240
- addIssue(
2241
- ctx,
2242
- ["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
2243
- `Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
2244
- );
2245
- return;
2246
- }
2247
- if (resource.kind !== "agent") {
2248
- addIssue(
2249
- ctx,
2250
- ["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
2251
- `Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
2252
- );
2253
- }
2254
- });
2255
- });
2256
- Object.entries(model.knowledge).forEach(([nodeId, node]) => {
2257
- node.ownerIds.forEach((roleId, ownerIndex) => {
2258
- if (!rolesById.has(roleId)) {
2259
- addIssue(
2260
- ctx,
2261
- ["knowledge", nodeId, "ownerIds", ownerIndex],
2262
- `Knowledge node "${node.id}" references unknown owner role "${roleId}"`
2263
- );
2264
- }
2265
- });
985
+ return OmTopologyNodeRefSchema.parse({ kind, id });
986
+ }
987
+ function defineTopologyRelationship(input) {
988
+ return OmTopologyRelationshipSchema.parse({
989
+ ...input,
990
+ from: compileTopologyNodeRef(input.from),
991
+ to: compileTopologyNodeRef(input.to)
2266
992
  });
2267
- for (const diagnostic of ontologyCompilation.diagnostics) {
2268
- addIssue(ctx, diagnostic.path, diagnostic.message);
2269
- }
2270
- });
2271
-
2272
- // ../core/src/organization-model/defaults.ts
2273
- var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
2274
- var DEFAULT_ORGANIZATION_MODEL_ENTITIES2 = {};
2275
- var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
2276
- sidebar: {
2277
- primary: {},
2278
- bottom: {}
2279
- }
2280
- };
2281
- var DEFAULT_ORGANIZATION_MODEL = {
2282
- version: 1,
2283
- domainMetadata: DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA,
2284
- branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
2285
- navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
2286
- identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
2287
- customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
2288
- offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
2289
- roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
2290
- goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
2291
- // Generic empty systems map. Elevasis-specific systems (platform, sales, sales.crm,
2292
- // sales.lead-gen, monitoring, settings, admin, etc.) have been relocated to
2293
- // `@repo/elevasis-core/src/organization-model/systems.ts` via `canonicalOrganizationModel`.
2294
- // Tenant OM configs supply their own systems via `resolveOrganizationModel`.
2295
- systems: {},
2296
- ontology: DEFAULT_ONTOLOGY_SCOPE,
2297
- resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
2298
- topology: DEFAULT_ORGANIZATION_MODEL_TOPOLOGY,
2299
- // Generic empty actions map. Elevasis-specific action entries have been relocated to
2300
- // `@repo/elevasis-core/src/organization-model/actions.ts`.
2301
- actions: {},
2302
- entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
2303
- policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
2304
- knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
2305
- };
2306
-
2307
- // ../core/src/organization-model/helpers.ts
2308
- function childSystemsOf2(system) {
2309
- return system.systems ?? system.subsystems ?? {};
2310
993
  }
2311
- function listAllSystems(model) {
2312
- const results = [];
2313
- function walk(map, prefix) {
2314
- for (const [localId, system] of Object.entries(map)) {
2315
- const fullPath = prefix ? `${prefix}.${localId}` : localId;
2316
- results.push({ path: fullPath, system });
2317
- const childSystems = childSystemsOf2(system);
2318
- if (Object.keys(childSystems).length > 0) {
2319
- walk(childSystems, fullPath);
2320
- }
2321
- }
2322
- }
2323
- walk(model.systems, "");
2324
- return results;
994
+ function defineTopology(relationships) {
995
+ const entries = Array.isArray(relationships) ? relationships.map((relationship, index) => [`relationship-${index + 1}`, relationship]) : Object.entries(relationships);
996
+ return OmTopologyDomainSchema.parse({
997
+ version: 1,
998
+ relationships: Object.fromEntries(entries.map(([key, relationship]) => [key, defineTopologyRelationship(relationship)]))
999
+ });
2325
1000
  }
2326
1001
 
2327
1002
  // ../core/src/organization-model/migration-helpers.ts
@@ -2387,80 +1062,6 @@ function getLeadGenStageCatalog(model) {
2387
1062
  Object.entries(results).sort(([, a], [, b]) => a.order - b.order || a.key.localeCompare(b.key))
2388
1063
  );
2389
1064
  }
2390
- var SalesStageSemanticClassSchema = z.enum(["open", "active", "nurturing", "closed_won", "closed_lost"]);
2391
- var SalesStageSchema = DisplayMetadataSchema.extend({
2392
- id: ModelIdSchema,
2393
- order: z.number().int().min(0),
2394
- semanticClass: SalesStageSemanticClassSchema,
2395
- surfaceIds: ReferenceIdsSchema,
2396
- resourceIds: ReferenceIdsSchema
2397
- });
2398
- z.object({
2399
- id: ModelIdSchema,
2400
- label: z.string().trim().min(1).max(120),
2401
- description: DescriptionSchema.optional(),
2402
- entityId: ModelIdSchema,
2403
- stages: z.array(SalesStageSchema).min(1)
2404
- });
2405
- var CRM_DISCOVERY_REPLIED_STATE = {
2406
- stateKey: "discovery_replied",
2407
- label: "Discovery Replied"
2408
- };
2409
- var CRM_DISCOVERY_LINK_SENT_STATE = {
2410
- stateKey: "discovery_link_sent",
2411
- label: "Discovery Link Sent"
2412
- };
2413
- var CRM_DISCOVERY_NUDGING_STATE = {
2414
- stateKey: "discovery_nudging",
2415
- label: "Discovery Nudging"
2416
- };
2417
- var CRM_DISCOVERY_BOOKING_CANCELLED_STATE = {
2418
- stateKey: "discovery_booking_cancelled",
2419
- label: "Discovery Booking Cancelled"
2420
- };
2421
- var CRM_REPLY_SENT_STATE = {
2422
- stateKey: "reply_sent",
2423
- label: "Reply Sent"
2424
- };
2425
- var CRM_FOLLOWUP_1_SENT_STATE = {
2426
- stateKey: "followup_1_sent",
2427
- label: "Follow-up 1 Sent"
2428
- };
2429
- var CRM_FOLLOWUP_2_SENT_STATE = {
2430
- stateKey: "followup_2_sent",
2431
- label: "Follow-up 2 Sent"
2432
- };
2433
- var CRM_FOLLOWUP_3_SENT_STATE = {
2434
- stateKey: "followup_3_sent",
2435
- label: "Follow-up 3 Sent"
2436
- };
2437
- var CRM_PIPELINE_DEFINITION = {
2438
- pipelineKey: "crm",
2439
- label: "CRM",
2440
- entityKey: "crm.deal",
2441
- stages: [
2442
- {
2443
- stageKey: "interested",
2444
- label: "Interested",
2445
- color: "blue",
2446
- states: [
2447
- CRM_DISCOVERY_REPLIED_STATE,
2448
- CRM_DISCOVERY_LINK_SENT_STATE,
2449
- CRM_DISCOVERY_NUDGING_STATE,
2450
- CRM_DISCOVERY_BOOKING_CANCELLED_STATE,
2451
- CRM_REPLY_SENT_STATE,
2452
- CRM_FOLLOWUP_1_SENT_STATE,
2453
- CRM_FOLLOWUP_2_SENT_STATE,
2454
- CRM_FOLLOWUP_3_SENT_STATE
2455
- ]
2456
- },
2457
- { stageKey: "proposal", label: "Proposal", color: "yellow", states: [] },
2458
- { stageKey: "closing", label: "Closing", color: "orange", states: [] },
2459
- { stageKey: "closed_won", label: "Closed Won", color: "green", states: [] },
2460
- { stageKey: "closed_lost", label: "Closed Lost", color: "red", states: [] },
2461
- { stageKey: "nurturing", label: "Nurturing", color: "grape", states: [] }
2462
- ]
2463
- };
2464
1065
  DisplayMetadataSchema.extend({
2465
1066
  id: ModelIdSchema,
2466
1067
  order: z.number().min(0)
@@ -2512,312 +1113,6 @@ var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
2512
1113
  id: ModelIdSchema,
2513
1114
  steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
2514
1115
  });
2515
- var DTC_RECORD_COLUMNS = {
2516
- populated: {
2517
- company: [
2518
- { key: "name", label: "Company", path: "company.name" },
2519
- { key: "domain", label: "Domain", path: "company.domain" },
2520
- { key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
2521
- { key: "apollo-industry", label: "Apollo industry", path: "company.category" },
2522
- { key: "location", label: "Location", path: "company.locationState" }
2523
- ]
2524
- },
2525
- crawled: {
2526
- company: [
2527
- { key: "name", label: "Company", path: "company.name" },
2528
- { key: "domain", label: "Domain", path: "company.domain" },
2529
- { key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
2530
- { key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
2531
- ]
2532
- },
2533
- extracted: {
2534
- company: [
2535
- { key: "name", label: "Company", path: "company.name" },
2536
- { key: "domain", label: "Domain", path: "company.domain" },
2537
- { key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
2538
- { key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
2539
- {
2540
- key: "automation-gaps",
2541
- label: "Automation gaps",
2542
- path: "company.enrichmentData.websiteCrawl.automationGaps",
2543
- renderType: "json"
2544
- },
2545
- {
2546
- key: "contact-count",
2547
- label: "Contacts",
2548
- path: "company.enrichmentData.websiteCrawl.emailCount",
2549
- renderType: "count"
2550
- }
2551
- ]
2552
- },
2553
- qualified: {
2554
- company: [
2555
- { key: "name", label: "Company", path: "company.name" },
2556
- { key: "domain", label: "Domain", path: "company.domain" },
2557
- { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
2558
- { key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
2559
- {
2560
- key: "disqualified-reason",
2561
- label: "Disqualified reason",
2562
- path: "processingState.qualified.data.disqualifiedReason"
2563
- }
2564
- ]
2565
- },
2566
- decisionMakers: {
2567
- contact: [
2568
- { key: "name", label: "Name", path: "contact.name" },
2569
- { key: "title", label: "Title", path: "contact.title" },
2570
- { key: "email", label: "Email", path: "contact.email" },
2571
- { key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
2572
- {
2573
- key: "priority-score",
2574
- label: "Priority",
2575
- path: "contact.enrichmentData.apollo.priorityScore",
2576
- renderType: "badge"
2577
- }
2578
- ]
2579
- },
2580
- uploaded: {
2581
- company: [
2582
- { key: "name", label: "Company", path: "company.name" },
2583
- { key: "domain", label: "Domain", path: "company.domain" },
2584
- {
2585
- key: "contacts",
2586
- label: "Contacts",
2587
- path: "company.enrichmentData.approvedLeadListExport.contacts",
2588
- renderType: "json"
2589
- },
2590
- { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
2591
- {
2592
- key: "approval",
2593
- label: "Approval",
2594
- path: "company.enrichmentData.approvedLeadListExport.approvalStatus",
2595
- renderType: "badge"
2596
- }
2597
- ]
2598
- }
2599
- };
2600
- var PROSPECTING_STEPS = {
2601
- localServices: {
2602
- sourceCompanies: {
2603
- id: "source-companies",
2604
- label: "Companies found",
2605
- primaryEntity: "company",
2606
- outputs: ["company"],
2607
- stageKey: "populated",
2608
- dependencyMode: "per-record-eligibility",
2609
- actionKey: "lead-gen.company.source",
2610
- defaultBatchSize: 100,
2611
- maxBatchSize: 250
2612
- },
2613
- analyzeWebsites: {
2614
- id: "analyze-websites",
2615
- label: "Websites analyzed",
2616
- primaryEntity: "company",
2617
- outputs: ["company"],
2618
- stageKey: "extracted",
2619
- dependsOn: ["source-companies"],
2620
- dependencyMode: "per-record-eligibility",
2621
- actionKey: "lead-gen.company.website-extract",
2622
- defaultBatchSize: 50,
2623
- maxBatchSize: 100
2624
- },
2625
- qualifyCompanies: {
2626
- id: "qualify-companies",
2627
- label: "Companies qualified",
2628
- primaryEntity: "company",
2629
- outputs: ["company"],
2630
- stageKey: "qualified",
2631
- dependsOn: ["analyze-websites"],
2632
- dependencyMode: "per-record-eligibility",
2633
- actionKey: "lead-gen.company.qualify",
2634
- defaultBatchSize: 100,
2635
- maxBatchSize: 250
2636
- },
2637
- findContacts: {
2638
- id: "find-contacts",
2639
- label: "Decision-makers found",
2640
- primaryEntity: "contact",
2641
- outputs: ["contact"],
2642
- stageKey: "discovered",
2643
- dependsOn: ["qualify-companies"],
2644
- dependencyMode: "per-record-eligibility",
2645
- actionKey: "lead-gen.contact.discover",
2646
- defaultBatchSize: 50,
2647
- maxBatchSize: 100
2648
- },
2649
- verifyEmails: {
2650
- id: "verify-emails",
2651
- label: "Emails verified",
2652
- primaryEntity: "contact",
2653
- outputs: ["contact"],
2654
- stageKey: "verified",
2655
- dependsOn: ["find-contacts"],
2656
- dependencyMode: "per-record-eligibility",
2657
- actionKey: "lead-gen.contact.verify-email",
2658
- defaultBatchSize: 100,
2659
- maxBatchSize: 500
2660
- },
2661
- personalize: {
2662
- id: "personalize",
2663
- label: "Personalize",
2664
- primaryEntity: "contact",
2665
- outputs: ["contact"],
2666
- stageKey: "personalized",
2667
- dependsOn: ["verify-emails"],
2668
- dependencyMode: "per-record-eligibility",
2669
- actionKey: "lead-gen.contact.personalize",
2670
- defaultBatchSize: 25,
2671
- maxBatchSize: 100
2672
- },
2673
- review: {
2674
- id: "review",
2675
- label: "Reviewed and exported",
2676
- primaryEntity: "contact",
2677
- outputs: ["export"],
2678
- stageKey: "uploaded",
2679
- dependsOn: ["personalize"],
2680
- dependencyMode: "per-record-eligibility",
2681
- actionKey: "lead-gen.review.outreach-ready",
2682
- defaultBatchSize: 25,
2683
- maxBatchSize: 100
2684
- }
2685
- },
2686
- dtcApolloClickup: {
2687
- importApolloSearch: {
2688
- id: "import-apollo-search",
2689
- label: "Companies found",
2690
- description: "Pull companies and seed contact data from a predefined Apollo search or list.",
2691
- primaryEntity: "company",
2692
- outputs: ["company", "contact"],
2693
- stageKey: "populated",
2694
- dependencyMode: "per-record-eligibility",
2695
- actionKey: "lead-gen.company.apollo-import",
2696
- defaultBatchSize: 250,
2697
- maxBatchSize: 1e3,
2698
- recordColumns: DTC_RECORD_COLUMNS.populated,
2699
- credentialRequirements: [
2700
- {
2701
- key: "apollo",
2702
- provider: "apollo",
2703
- credentialType: "api-key-secret",
2704
- label: "Apollo API key",
2705
- required: true,
2706
- selectionMode: "single",
2707
- inputPath: "credential"
2708
- }
2709
- ]
2710
- },
2711
- apifyCrawl: {
2712
- id: "apify-crawl",
2713
- label: "Websites crawled",
2714
- description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis. Overwrites the synthetic seed Apollo Import wrote with real page content.",
2715
- primaryEntity: "company",
2716
- outputs: ["company"],
2717
- stageKey: "crawled",
2718
- dependsOn: ["import-apollo-search"],
2719
- dependencyMode: "per-record-eligibility",
2720
- actionKey: "lead-gen.company.apify-crawl",
2721
- defaultBatchSize: 50,
2722
- maxBatchSize: 100,
2723
- recordColumns: DTC_RECORD_COLUMNS.crawled,
2724
- credentialRequirements: [
2725
- {
2726
- key: "apify",
2727
- provider: "apify",
2728
- credentialType: "api-key-secret",
2729
- label: "Apify API token",
2730
- required: true,
2731
- selectionMode: "single",
2732
- inputPath: "credential",
2733
- verifyOnRun: true
2734
- }
2735
- ]
2736
- },
2737
- analyzeWebsites: {
2738
- id: "analyze-websites",
2739
- label: "Websites analyzed",
2740
- description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
2741
- primaryEntity: "company",
2742
- outputs: ["company"],
2743
- stageKey: "extracted",
2744
- dependsOn: ["apify-crawl"],
2745
- dependencyMode: "per-record-eligibility",
2746
- actionKey: "lead-gen.company.website-extract",
2747
- defaultBatchSize: 50,
2748
- maxBatchSize: 100,
2749
- recordColumns: DTC_RECORD_COLUMNS.extracted
2750
- },
2751
- scoreDtcFit: {
2752
- id: "score-dtc-fit",
2753
- label: "Companies qualified",
2754
- description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
2755
- primaryEntity: "company",
2756
- outputs: ["company"],
2757
- stageKey: "qualified",
2758
- dependsOn: ["analyze-websites"],
2759
- dependencyMode: "per-record-eligibility",
2760
- actionKey: "lead-gen.company.dtc-subscription-qualify",
2761
- defaultBatchSize: 100,
2762
- maxBatchSize: 250,
2763
- recordColumns: DTC_RECORD_COLUMNS.qualified
2764
- },
2765
- enrichDecisionMakers: {
2766
- id: "enrich-decision-makers",
2767
- label: "Decision-makers found",
2768
- description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
2769
- primaryEntity: "company",
2770
- outputs: ["contact"],
2771
- stageKey: "decision-makers-enriched",
2772
- recordEntity: "contact",
2773
- dependsOn: ["score-dtc-fit"],
2774
- dependencyMode: "per-record-eligibility",
2775
- actionKey: "lead-gen.contact.apollo-decision-maker-enrich",
2776
- defaultBatchSize: 100,
2777
- maxBatchSize: 250,
2778
- recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
2779
- credentialRequirements: [
2780
- {
2781
- key: "apollo",
2782
- provider: "apollo",
2783
- credentialType: "api-key-secret",
2784
- label: "Apollo API key",
2785
- required: true,
2786
- selectionMode: "single",
2787
- inputPath: "credential"
2788
- }
2789
- ]
2790
- },
2791
- reviewAndExport: {
2792
- id: "review-and-export",
2793
- label: "Reviewed and exported",
2794
- description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
2795
- primaryEntity: "company",
2796
- outputs: ["export"],
2797
- stageKey: "uploaded",
2798
- recordsStageKey: "uploaded",
2799
- recordSourceStageKey: "qualified",
2800
- dependsOn: ["enrich-decision-makers"],
2801
- dependencyMode: "per-record-eligibility",
2802
- actionKey: "lead-gen.export.list",
2803
- defaultBatchSize: 100,
2804
- maxBatchSize: 250,
2805
- recordColumns: DTC_RECORD_COLUMNS.uploaded,
2806
- credentialRequirements: [
2807
- {
2808
- key: "clickup",
2809
- provider: "clickup",
2810
- credentialType: "api-key-secret",
2811
- label: "ClickUp API token",
2812
- required: true,
2813
- selectionMode: "single",
2814
- inputPath: "clickupCredential",
2815
- verifyOnRun: true
2816
- }
2817
- ]
2818
- }
2819
- }
2820
- };
2821
1116
 
2822
1117
  // src/contract-ref.ts
2823
1118
  var ContractRefResolutionError = class extends Error {
@@ -6854,300 +5149,67 @@ var ResourceRegistry = class {
6854
5149
  * Use for API responses - returns pre-computed JSON-safe structure
6855
5150
  *
6856
5151
  * @param organizationName - Organization name
6857
- * @param resourceId - Resource ID
6858
- * @returns Serialized definition or null if not found
6859
- */
6860
- getSerializedDefinition(organizationName, resourceId) {
6861
- const cache = this.serializedCache.get(organizationName);
6862
- if (!cache) return null;
6863
- return cache.definitions.agents.get(resourceId) ?? cache.definitions.workflows.get(resourceId) ?? null;
6864
- }
6865
- /**
6866
- * Get resource list for organization (instant lookup)
6867
- * Use for /resources endpoint - returns pre-computed ResourceDefinition array
6868
- *
6869
- * @param organizationName - Organization name
6870
- * @returns Resource list with workflows, agents, and total count
6871
- */
6872
- getResourceList(organizationName) {
6873
- const cache = this.serializedCache.get(organizationName);
6874
- if (!cache) {
6875
- return { workflows: [], agents: [], total: 0 };
6876
- }
6877
- return cache.resources;
6878
- }
6879
- /**
6880
- * Get Command View data for organization (instant lookup)
6881
- * Use for /command-view endpoint - returns complete graph data
6882
- *
6883
- * @param organizationName - Organization name
6884
- * @returns Command View data with nodes and edges
6885
- */
6886
- getCommandViewData(organizationName) {
6887
- const cache = this.serializedCache.get(organizationName);
6888
- if (!cache) {
6889
- return {
6890
- workflows: [],
6891
- agents: [],
6892
- triggers: [],
6893
- integrations: [],
6894
- externalResources: [],
6895
- humanCheckpoints: [],
6896
- edges: []
6897
- };
6898
- }
6899
- return cache.commandView;
6900
- }
6901
- };
6902
-
6903
- // ../core/src/platform/registry/types.ts
6904
- function bindResourceDescriptor(definition) {
6905
- const { resource, ...rest } = definition;
6906
- return {
6907
- ...rest,
6908
- resource,
6909
- resourceId: resource.id,
6910
- type: resource.kind
6911
- };
6912
- }
6913
-
6914
- // ../core/src/business/acquisition/build-templates.ts
6915
- var BUILD_TEMPLATE_CATALOG = [
6916
- {
6917
- id: "local-services",
6918
- label: "Local Services",
6919
- description: "Source, analyze, qualify, and personalize local service businesses for outreach.",
6920
- steps: Object.values(PROSPECTING_STEPS.localServices)
6921
- },
6922
- {
6923
- id: "dtc-subscription-apollo-clickup",
6924
- label: "DTC Subscription (Apollo + ClickUp)",
6925
- description: "Import DTC brand leads from Apollo, crawl their websites, score fit, enrich contacts, and export via ClickUp.",
6926
- steps: Object.values(PROSPECTING_STEPS.dtcApolloClickup)
6927
- }
6928
- ];
6929
- var PROSPECTING_BUILD_TEMPLATE_OPTIONS = BUILD_TEMPLATE_CATALOG.map(({ id, label, description }) => ({
6930
- id,
6931
- label,
6932
- description
6933
- }));
6934
- function isProspectingBuildTemplateId(value) {
6935
- return PROSPECTING_BUILD_TEMPLATE_OPTIONS.some((template) => template.id === value);
6936
- }
6937
-
6938
- // ../core/src/business/acquisition/ontology-validation.ts
6939
- var CRM_PIPELINE_CATALOG_ONTOLOGY_ID = formatOntologyId({
6940
- scope: "sales.crm",
6941
- kind: "catalog",
6942
- localId: "crm.pipeline"
6943
- });
6944
- var LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
6945
- scope: "sales.lead-gen",
6946
- kind: "catalog",
6947
- localId: "lead-gen.stage-catalog"
6948
- });
6949
- var CRM_DEAL_OBJECT_ONTOLOGY_ID = formatOntologyId({
6950
- scope: "sales.crm",
6951
- kind: "object",
6952
- localId: "crm.deal"
6953
- });
6954
- function createCrmPipelineCatalog() {
6955
- return {
6956
- id: CRM_PIPELINE_CATALOG_ONTOLOGY_ID,
6957
- label: CRM_PIPELINE_DEFINITION.label,
6958
- ownerSystemId: "sales.crm",
6959
- kind: "pipeline",
6960
- appliesTo: CRM_DEAL_OBJECT_ONTOLOGY_ID,
6961
- entries: Object.fromEntries(
6962
- CRM_PIPELINE_DEFINITION.stages.map((stage, index) => [
6963
- stage.stageKey,
6964
- {
6965
- key: stage.stageKey,
6966
- label: stage.label,
6967
- order: (index + 1) * 10,
6968
- ...stage.color !== void 0 ? { color: stage.color } : {},
6969
- states: stage.states.map((state) => ({ ...state }))
6970
- }
6971
- ])
6972
- ),
6973
- legacyPipelineKey: CRM_PIPELINE_DEFINITION.pipelineKey,
6974
- legacyEntityKey: CRM_PIPELINE_DEFINITION.entityKey
6975
- };
6976
- }
6977
- function createLeadGenStageCatalog(model) {
6978
- return {
6979
- id: LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID,
6980
- label: "Lead Gen Processing Stages",
6981
- ownerSystemId: "sales.lead-gen",
6982
- kind: "processing-stage-catalog",
6983
- entries: Object.fromEntries(
6984
- Object.entries(getLeadGenStageCatalog(model)).map(([key, entry]) => [
6985
- key,
6986
- {
6987
- ...entry
6988
- }
6989
- ])
6990
- ),
6991
- legacyCatalogKey: "LEAD_GEN_STAGE_CATALOG"
6992
- };
6993
- }
6994
- function isPlainRecord(value) {
6995
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6996
- }
6997
- function mergeBridgeCatalogs(model) {
6998
- const baseCatalogTypes = model.ontology?.catalogTypes ?? {};
6999
- const bridgeCatalogTypes = {};
7000
- if (baseCatalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID] === void 0) {
7001
- bridgeCatalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID] = createCrmPipelineCatalog();
7002
- }
7003
- if (baseCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] === void 0) {
7004
- bridgeCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] = createLeadGenStageCatalog(model);
5152
+ * @param resourceId - Resource ID
5153
+ * @returns Serialized definition or null if not found
5154
+ */
5155
+ getSerializedDefinition(organizationName, resourceId) {
5156
+ const cache = this.serializedCache.get(organizationName);
5157
+ if (!cache) return null;
5158
+ return cache.definitions.agents.get(resourceId) ?? cache.definitions.workflows.get(resourceId) ?? null;
7005
5159
  }
7006
- if (Object.keys(bridgeCatalogTypes).length === 0) return model;
7007
- return {
7008
- ...model,
7009
- ontology: {
7010
- ...model.ontology ?? {},
7011
- catalogTypes: {
7012
- ...baseCatalogTypes,
7013
- ...bridgeCatalogTypes
7014
- }
5160
+ /**
5161
+ * Get resource list for organization (instant lookup)
5162
+ * Use for /resources endpoint - returns pre-computed ResourceDefinition array
5163
+ *
5164
+ * @param organizationName - Organization name
5165
+ * @returns Resource list with workflows, agents, and total count
5166
+ */
5167
+ getResourceList(organizationName) {
5168
+ const cache = this.serializedCache.get(organizationName);
5169
+ if (!cache) {
5170
+ return { workflows: [], agents: [], total: 0 };
7015
5171
  }
7016
- };
7017
- }
7018
- function compileBusinessOntologyValidationIndex(model = DEFAULT_ORGANIZATION_MODEL) {
7019
- const compilation = compileOrganizationOntology(mergeBridgeCatalogs(model));
7020
- if (compilation.diagnostics.length > 0) {
7021
- const summary = compilation.diagnostics.map((diagnostic) => diagnostic.message).join("; ");
7022
- throw new Error(`Business ontology validation index failed to compile: ${summary}`);
7023
- }
7024
- const crmPipelineCatalog = compilation.ontology.catalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID];
7025
- const leadGenStageCatalog = compilation.ontology.catalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID];
7026
- if (crmPipelineCatalog === void 0 || leadGenStageCatalog === void 0) {
7027
- throw new Error("Business ontology validation index is missing CRM or lead-gen catalog bridge records");
5172
+ return cache.resources;
7028
5173
  }
7029
- return {
7030
- ontology: compilation.ontology,
7031
- crmPipelineCatalog,
7032
- leadGenStageCatalog,
7033
- actionTypesByLegacyId: indexActionTypesByLegacyId(compilation.ontology.actionTypes)
7034
- };
7035
- }
7036
- function indexActionTypesByLegacyId(actionTypes) {
7037
- const byLegacyId = {};
7038
- for (const actionType of Object.values(actionTypes)) {
7039
- const legacyActionId = actionType["legacyActionId"];
7040
- if (typeof legacyActionId === "string") {
7041
- byLegacyId[legacyActionId] = actionType;
5174
+ /**
5175
+ * Get Command View data for organization (instant lookup)
5176
+ * Use for /command-view endpoint - returns complete graph data
5177
+ *
5178
+ * @param organizationName - Organization name
5179
+ * @returns Command View data with nodes and edges
5180
+ */
5181
+ getCommandViewData(organizationName) {
5182
+ const cache = this.serializedCache.get(organizationName);
5183
+ if (!cache) {
5184
+ return {
5185
+ workflows: [],
5186
+ agents: [],
5187
+ triggers: [],
5188
+ integrations: [],
5189
+ externalResources: [],
5190
+ humanCheckpoints: [],
5191
+ edges: []
5192
+ };
7042
5193
  }
5194
+ return cache.commandView;
7043
5195
  }
7044
- return byLegacyId;
7045
- }
7046
- var BUSINESS_ONTOLOGY_VALIDATION_INDEX = compileBusinessOntologyValidationIndex();
7047
- function getCatalogEntries(catalog) {
7048
- return isPlainRecord(catalog.entries) ? catalog.entries : {};
7049
- }
7050
- function asCrmStageEntry(key, value) {
7051
- const record = isPlainRecord(value) ? value : {};
7052
- const label = typeof record.label === "string" ? record.label : key;
7053
- const order = typeof record.order === "number" ? record.order : 0;
7054
- const color = typeof record.color === "string" ? record.color : void 0;
7055
- const rawStates = Array.isArray(record.states) ? record.states : [];
7056
- const states = rawStates.flatMap((state) => {
7057
- if (!isPlainRecord(state) || typeof state.stateKey !== "string") return [];
7058
- return [
7059
- {
7060
- stateKey: state.stateKey,
7061
- label: typeof state.label === "string" ? state.label : state.stateKey
7062
- }
7063
- ];
7064
- });
5196
+ };
5197
+
5198
+ // ../core/src/platform/registry/types.ts
5199
+ function bindResourceDescriptor(definition) {
5200
+ const { resource, ...rest } = definition;
7065
5201
  return {
7066
- key,
7067
- label,
7068
- order,
7069
- ...color !== void 0 ? { color } : {},
7070
- states
5202
+ ...rest,
5203
+ resource,
5204
+ resourceId: resource.id,
5205
+ type: resource.kind
7071
5206
  };
7072
5207
  }
7073
- var CRM_STAGE_KEYS_FROM_ONTOLOGY = Object.keys(
7074
- getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.crmPipelineCatalog)
7075
- );
7076
- var CRM_STATE_KEYS_FROM_ONTOLOGY = Object.values(
7077
- getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.crmPipelineCatalog)
7078
- ).flatMap((entry, index) => {
7079
- const stageKey = CRM_STAGE_KEYS_FROM_ONTOLOGY[index];
7080
- if (stageKey === void 0) return [];
7081
- return asCrmStageEntry(stageKey, entry).states.map((state) => state.stateKey);
7082
- });
7083
- Object.keys(
7084
- getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.leadGenStageCatalog)
7085
- );
7086
-
7087
- // ../core/src/business/acquisition/deal-ownership.ts
7088
- var INBOUND_EVENT_TYPES = ["reply_received"];
7089
- var OUTBOUND_EVENT_TYPES = [
7090
- "reply_sent_to_lead",
7091
- "booking_nudge_sent",
7092
- "reminder_sent",
7093
- "rebook_sent",
7094
- "followup_email_sent",
7095
- "reply_followup_sent",
7096
- "lead_deferred_next_step"
7097
- ];
7098
- var INBOUND_SET = new Set(INBOUND_EVENT_TYPES);
7099
- var OUTBOUND_SET = new Set(OUTBOUND_EVENT_TYPES);
7100
- function getDealOwnership(deal) {
7101
- if (deal.state_key === "closed_won" || deal.state_key === "closed_lost") {
7102
- return null;
7103
- }
7104
- if (!Array.isArray(deal.activity_log)) return null;
7105
- let latestInboundMs = null;
7106
- let latestOutboundMs = null;
7107
- for (const entry of deal.activity_log) {
7108
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
7109
- const record = entry;
7110
- const type = typeof record.type === "string" ? record.type : null;
7111
- if (!type) continue;
7112
- const isInbound = INBOUND_SET.has(type);
7113
- const isOutbound = OUTBOUND_SET.has(type);
7114
- if (!isInbound && !isOutbound) continue;
7115
- const occurredAt = resolveTimestamp(record);
7116
- if (occurredAt === null) continue;
7117
- if (isInbound && (latestInboundMs === null || occurredAt > latestInboundMs)) {
7118
- latestInboundMs = occurredAt;
7119
- }
7120
- if (isOutbound && (latestOutboundMs === null || occurredAt > latestOutboundMs)) {
7121
- latestOutboundMs = occurredAt;
7122
- }
7123
- }
7124
- if (latestInboundMs === null && latestOutboundMs === null) return null;
7125
- if (latestOutboundMs !== null && (latestInboundMs === null || latestOutboundMs >= latestInboundMs)) {
7126
- return "them";
7127
- }
7128
- return "us";
7129
- }
7130
- function resolveTimestamp(record) {
7131
- return parseMs(record.timestamp) ?? parseMs(record.occurredAt) ?? parseMs(record.createdAt) ?? parseMs(record.updatedAt) ?? parseMs(record.sentAt) ?? null;
7132
- }
7133
- function parseMs(value) {
7134
- if (value instanceof Date) {
7135
- const ms2 = value.getTime();
7136
- return Number.isNaN(ms2) ? null : ms2;
7137
- }
7138
- if (typeof value !== "string") return null;
7139
- const ms = new Date(value).getTime();
7140
- return Number.isNaN(ms) ? null : ms;
7141
- }
7142
-
7143
- // ../core/src/business/acquisition/api-schemas.ts
7144
5208
  var ProcessingStageStatusSchema = z.enum(["success", "no_result", "skipped", "error"]);
7145
5209
  var LeadGenStageKeySchema = z.string().trim().min(1);
7146
5210
  var LeadGenActionKeySchema = z.string().trim().min(1);
7147
- var crmStageKeys = CRM_STAGE_KEYS_FROM_ONTOLOGY;
7148
- var crmStateKeys = CRM_STATE_KEYS_FROM_ONTOLOGY;
7149
- var CrmStageKeySchema = z.enum(crmStageKeys);
7150
- var CrmStateKeySchema = z.enum(crmStateKeys);
5211
+ var CrmStageKeySchema = z.string().trim().min(1);
5212
+ var CrmStateKeySchema = z.string().trim().min(1);
7151
5213
  var ProcessingStateEntrySchema = z.object({
7152
5214
  status: ProcessingStageStatusSchema,
7153
5215
  data: z.unknown().optional()
@@ -7405,8 +5467,10 @@ var PipelineStageSchema = z.object({
7405
5467
  enabled: z.boolean().optional(),
7406
5468
  order: z.number().int().optional()
7407
5469
  });
5470
+ var DataModeSchema = z.enum(["mock", "live"]);
7408
5471
  var PipelineConfigSchema = z.object({
7409
- stages: z.array(PipelineStageSchema).optional()
5472
+ stages: z.array(PipelineStageSchema).optional(),
5473
+ dataMode: DataModeSchema.optional()
7410
5474
  });
7411
5475
  var BuildPlanSnapshotStepSchema = z.object({
7412
5476
  id: z.string().trim().min(1).max(100),
@@ -7463,9 +5527,7 @@ var BuildPlanSnapshotSchema = z.object({
7463
5527
  var AcqListMetadataSchema = z.object({
7464
5528
  buildPlanSnapshot: BuildPlanSnapshotSchema.optional()
7465
5529
  }).catchall(z.unknown());
7466
- var ProspectingBuildTemplateIdSchema = z.string().trim().min(1).max(100).refine(isProspectingBuildTemplateId, {
7467
- message: "buildTemplateId must match a known prospecting build template"
7468
- });
5530
+ var ProspectingBuildTemplateIdSchema = z.string().trim().min(1).max(100);
7469
5531
  var ListStageCountsSchema = z.object({
7470
5532
  // Attempted counts by canonical lead-gen stage. The detailed status
7471
5533
  // distribution lives on ListProgress; telemetry keeps the overview payload small.
@@ -8044,116 +6106,280 @@ var ActivityEventSchema = z.discriminatedUnion("type", [
8044
6106
  DealCreatedEventSchema,
8045
6107
  ActionFailedEventSchema
8046
6108
  ]);
8047
- var SendReplyActionPayloadSchema = z.object({
6109
+ z.object({
8048
6110
  replyBody: z.string().trim().min(1).max(1e4)
8049
6111
  }).strict();
8050
- var CRM_RUNTIME_ACTION_METADATA = {
8051
- move_to_proposal: {
8052
- key: "move_to_proposal",
8053
- label: "Move to Proposal",
8054
- workflowId: "move_to_proposal-workflow"
8055
- },
8056
- move_to_closing: {
8057
- key: "move_to_closing",
8058
- label: "Move to Closing",
8059
- workflowId: "move_to_closing-workflow"
8060
- },
8061
- move_to_closed_won: {
8062
- key: "move_to_closed_won",
8063
- label: "Close Won",
8064
- workflowId: "move_to_closed_won-workflow"
8065
- },
8066
- move_to_closed_lost: {
8067
- key: "move_to_closed_lost",
8068
- label: "Close Lost",
8069
- workflowId: "move_to_closed_lost-workflow"
8070
- },
8071
- move_to_nurturing: {
8072
- key: "move_to_nurturing",
8073
- label: "Move to Nurturing",
8074
- workflowId: "move_to_nurturing-workflow"
8075
- },
8076
- send_reply: {
8077
- key: "send_reply",
8078
- label: "Send Reply",
8079
- workflowId: "crm-send-reply-workflow"
8080
- },
8081
- send_link: {
8082
- key: "send_link",
8083
- label: "Send Booking Link",
8084
- workflowId: "crm-send-booking-link-workflow"
8085
- },
8086
- send_nudge: {
8087
- key: "send_nudge",
8088
- label: "Send Nudge",
8089
- workflowId: "crm-send-nudge-workflow"
8090
- },
8091
- rebook: {
8092
- key: "rebook",
8093
- label: "Rebook",
8094
- workflowId: "crm-rebook-workflow"
6112
+ function deriveActions(deal, actions = []) {
6113
+ return actions.filter((a) => a.isAvailableFor(deal)).map(({ key, label, payloadSchema }) => ({ key, label, payloadSchema }));
6114
+ }
6115
+
6116
+ // ../core/src/business/acquisition/ontology-validation.ts
6117
+ var CRM_PIPELINE_CATALOG_ONTOLOGY_ID = formatOntologyId({
6118
+ scope: "sales.crm",
6119
+ kind: "catalog",
6120
+ localId: "crm.pipeline"
6121
+ });
6122
+ var LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
6123
+ scope: "sales.lead-gen",
6124
+ kind: "catalog",
6125
+ localId: "lead-gen.stage-catalog"
6126
+ });
6127
+ function createLeadGenStageCatalog(model) {
6128
+ return {
6129
+ id: LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID,
6130
+ label: "Lead Gen Processing Stages",
6131
+ ownerSystemId: "sales.lead-gen",
6132
+ kind: "processing-stage-catalog",
6133
+ entries: Object.fromEntries(
6134
+ Object.entries(getLeadGenStageCatalog(model)).map(([key, entry]) => [
6135
+ key,
6136
+ {
6137
+ ...entry
6138
+ }
6139
+ ])
6140
+ ),
6141
+ legacyCatalogKey: "LEAD_GEN_STAGE_CATALOG"
6142
+ };
6143
+ }
6144
+ function isPlainRecord(value) {
6145
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
6146
+ }
6147
+ function mergeBridgeCatalogs(model) {
6148
+ const baseCatalogTypes = model.ontology?.catalogTypes ?? {};
6149
+ const bridgeCatalogTypes = {};
6150
+ if (baseCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] === void 0) {
6151
+ bridgeCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] = createLeadGenStageCatalog(model);
8095
6152
  }
8096
- };
8097
- function crmAction(actionId, runtime) {
8098
- const metadata = CRM_RUNTIME_ACTION_METADATA[actionId];
8099
- if (!metadata?.workflowId) {
8100
- throw new Error(`CRM action metadata for "${actionId}" must define resourceId`);
6153
+ if (Object.keys(bridgeCatalogTypes).length === 0) return model;
6154
+ return {
6155
+ ...model,
6156
+ ontology: {
6157
+ ...model.ontology ?? {},
6158
+ catalogTypes: {
6159
+ ...baseCatalogTypes,
6160
+ ...bridgeCatalogTypes
6161
+ }
6162
+ }
6163
+ };
6164
+ }
6165
+ function compileBusinessOntologyValidationIndex(model) {
6166
+ const compilation = compileOrganizationOntology(mergeBridgeCatalogs(model));
6167
+ if (compilation.diagnostics.length > 0) {
6168
+ const summary = compilation.diagnostics.map((diagnostic) => diagnostic.message).join("; ");
6169
+ throw new Error(`Business ontology validation index failed to compile: ${summary}`);
6170
+ }
6171
+ const crmPipelineCatalog = compilation.ontology.catalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID];
6172
+ const leadGenStageCatalog = compilation.ontology.catalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID];
6173
+ if (crmPipelineCatalog === void 0 || leadGenStageCatalog === void 0) {
6174
+ throw new Error("Business ontology validation index is missing CRM or lead-gen catalog bridge records");
8101
6175
  }
8102
6176
  return {
8103
- key: metadata.key,
8104
- label: metadata.label,
8105
- workflowId: metadata.workflowId,
8106
- ...runtime
6177
+ ontology: compilation.ontology,
6178
+ crmPipelineCatalog,
6179
+ leadGenStageCatalog,
6180
+ actionTypesByLegacyId: indexActionTypesByLegacyId(compilation.ontology.actionTypes)
8107
6181
  };
8108
6182
  }
8109
- var DEFAULT_CRM_ACTIONS = [
8110
- crmAction("move_to_proposal", {
8111
- isAvailableFor: (deal) => deal.stage_key === "interested"
8112
- }),
8113
- crmAction("move_to_closing", {
8114
- isAvailableFor: (deal) => deal.stage_key === "proposal"
8115
- }),
8116
- crmAction("move_to_closed_won", {
8117
- isAvailableFor: (deal) => deal.stage_key === "closing"
8118
- }),
8119
- crmAction("move_to_closed_lost", {
8120
- isAvailableFor: (deal) => deal.stage_key === "interested" || deal.stage_key === "proposal" || deal.stage_key === "closing"
8121
- }),
8122
- crmAction("move_to_nurturing", {
8123
- isAvailableFor: (deal) => deal.stage_key === "interested" || deal.stage_key === "proposal" || deal.stage_key === "closing"
8124
- }),
8125
- crmAction("send_reply", {
8126
- 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),
8127
- payloadSchema: SendReplyActionPayloadSchema
8128
- }),
8129
- crmAction("send_link", {
8130
- isAvailableFor: (deal) => deal.stage_key === "interested" && deal.state_key === CRM_DISCOVERY_REPLIED_STATE.stateKey
8131
- }),
8132
- crmAction("send_nudge", {
8133
- isAvailableFor: (deal) => deal.stage_key === "interested" && (deal.state_key === CRM_DISCOVERY_LINK_SENT_STATE.stateKey || deal.state_key === CRM_DISCOVERY_NUDGING_STATE.stateKey)
8134
- }),
8135
- {
8136
- key: "mark_no_show",
8137
- label: "Mark No-Show",
8138
- isAvailableFor: (deal) => deal.stage_key === "interested" && deal.state_key === CRM_DISCOVERY_NUDGING_STATE.stateKey,
8139
- // Mirrors the auto-timeout precedent in operations/sales/crm/pipeline/timeout-actions.ts:
8140
- // both manual-click and timeout move the deal to closed_lost. The action_taken activity
8141
- // event captures operator intent and distinguishes the manual variant from the timed one.
8142
- workflowId: "mark_no_show-workflow"
8143
- },
8144
- crmAction("rebook", {
8145
- isAvailableFor: (deal) => deal.stage_key === "interested" && deal.state_key === CRM_DISCOVERY_BOOKING_CANCELLED_STATE.stateKey
8146
- })
8147
- ];
8148
- function deriveActions(deal, actions = DEFAULT_CRM_ACTIONS) {
8149
- return actions.filter((a) => a.isAvailableFor(deal)).map(({ key, label, payloadSchema }) => ({ key, label, payloadSchema }));
6183
+ function indexActionTypesByLegacyId(actionTypes) {
6184
+ const byLegacyId = {};
6185
+ for (const actionType of Object.values(actionTypes)) {
6186
+ const legacyActionId = actionType["legacyActionId"];
6187
+ if (typeof legacyActionId === "string") {
6188
+ byLegacyId[legacyActionId] = actionType;
6189
+ }
6190
+ }
6191
+ return byLegacyId;
6192
+ }
6193
+ function getCatalogEntries(catalog) {
6194
+ return isPlainRecord(catalog.entries) ? catalog.entries : {};
6195
+ }
6196
+ function asLeadGenStageEntry(key, value) {
6197
+ const record = isPlainRecord(value) ? value : {};
6198
+ const entity = record.entity === "contact" ? "contact" : "company";
6199
+ const additionalEntities = Array.isArray(record.additionalEntities) ? record.additionalEntities.filter(
6200
+ (item) => item === "company" || item === "contact"
6201
+ ) : void 0;
6202
+ const recordEntity = record.recordEntity === "company" || record.recordEntity === "contact" ? record.recordEntity : void 0;
6203
+ const recordStageKey = typeof record.recordStageKey === "string" ? record.recordStageKey : void 0;
6204
+ return {
6205
+ key: typeof record.key === "string" ? record.key : key,
6206
+ label: typeof record.label === "string" ? record.label : key,
6207
+ description: typeof record.description === "string" ? record.description : "",
6208
+ order: typeof record.order === "number" ? record.order : 0,
6209
+ entity,
6210
+ ...additionalEntities !== void 0 ? { additionalEntities } : {},
6211
+ ...recordEntity !== void 0 ? { recordEntity } : {},
6212
+ ...recordStageKey !== void 0 ? { recordStageKey } : {}
6213
+ };
6214
+ }
6215
+ function createLeadGenStageValidators(index) {
6216
+ const getCatalog = () => Object.fromEntries(
6217
+ Object.entries(getCatalogEntries(index.leadGenStageCatalog)).map(([key, value]) => [
6218
+ key,
6219
+ asLeadGenStageEntry(key, value)
6220
+ ])
6221
+ );
6222
+ const getEntry = (stageKey) => getCatalog()[stageKey];
6223
+ return {
6224
+ getLeadGenStageCatalog: getCatalog,
6225
+ getLeadGenStageEntry: getEntry,
6226
+ isLeadGenStageKey: (stageKey) => getEntry(stageKey) !== void 0,
6227
+ isLeadGenStageValidForEntity: (stageKey, entity) => {
6228
+ const stage = getEntry(stageKey);
6229
+ return stage !== void 0 && (stage.entity === entity || stage.additionalEntities?.includes(entity) === true);
6230
+ },
6231
+ isLeadGenRecordStageValidForEntity: (stageKey, entity) => {
6232
+ const stage = getEntry(stageKey);
6233
+ return stage !== void 0 && (stage.entity === entity || stage.additionalEntities?.includes(entity) === true || stage.recordEntity === entity);
6234
+ },
6235
+ resolveLeadGenRecordStageKey: (stageKey, entity) => {
6236
+ const stage = getEntry(stageKey);
6237
+ return stage?.recordEntity === entity && stage.recordStageKey ? stage.recordStageKey : stageKey;
6238
+ }
6239
+ };
6240
+ }
6241
+
6242
+ // src/project-deployment-spec.ts
6243
+ function toSdkResourceDescriptor(resource, getResourceOntologyBinding) {
6244
+ const ontologyBinding = getResourceOntologyBinding?.(resource.id);
6245
+ return {
6246
+ ...resource,
6247
+ ...ontologyBinding ?? {},
6248
+ systemId: resource.systemPath
6249
+ };
6250
+ }
6251
+ function withPlatformResourceDescriptor(workflow, getWorkflowResourceDescriptor, getResourceOntologyBinding) {
6252
+ const resource = getWorkflowResourceDescriptor(workflow.config.resourceId);
6253
+ const sdkResource = toSdkResourceDescriptor(resource, getResourceOntologyBinding);
6254
+ return {
6255
+ ...workflow,
6256
+ config: {
6257
+ ...workflow.config,
6258
+ resource: sdkResource,
6259
+ resourceId: sdkResource.id,
6260
+ type: sdkResource.kind
6261
+ }
6262
+ };
6263
+ }
6264
+ function withPlatformResourceDescriptors(workflows, getWorkflowResourceDescriptor, getResourceOntologyBinding) {
6265
+ return workflows.map(
6266
+ (workflow) => withPlatformResourceDescriptor(workflow, getWorkflowResourceDescriptor, getResourceOntologyBinding)
6267
+ );
6268
+ }
6269
+ function withPlatformIntegrationResourceDescriptor(integration, getIntegrationResourceDescriptor, getResourceOntologyBinding) {
6270
+ const resource = getIntegrationResourceDescriptor(integration.resourceId);
6271
+ const sdkResource = toSdkResourceDescriptor(resource, getResourceOntologyBinding);
6272
+ return {
6273
+ ...integration,
6274
+ resource: sdkResource,
6275
+ resourceId: sdkResource.id,
6276
+ type: sdkResource.kind
6277
+ };
6278
+ }
6279
+ function withPlatformIntegrationResourceDescriptors(integrations, getIntegrationResourceDescriptor, getResourceOntologyBinding) {
6280
+ return integrations.map(
6281
+ (integration) => withPlatformIntegrationResourceDescriptor(integration, getIntegrationResourceDescriptor, getResourceOntologyBinding)
6282
+ );
8150
6283
  }
8151
- function isOurReplyAction(deal) {
8152
- if (Object.prototype.hasOwnProperty.call(deal, "nextAction")) {
8153
- return deal.nextAction === "send_reply";
6284
+ function projectTopologyRelationships(model) {
6285
+ const projected = {};
6286
+ function ensure(sourceId) {
6287
+ projected[sourceId] ??= {};
6288
+ return projected[sourceId];
6289
+ }
6290
+ for (const relationship of Object.values(model.topology.relationships)) {
6291
+ if (relationship.from.kind === "humanCheckpoint") continue;
6292
+ if (relationship.kind === "triggers" && relationship.to.kind === "resource") {
6293
+ const target = model.resources[relationship.to.id];
6294
+ if (target?.kind !== "workflow" && target?.kind !== "agent") continue;
6295
+ const source = ensure(relationship.from.id);
6296
+ source.triggers ??= {};
6297
+ if (target.kind === "workflow") {
6298
+ source.triggers.workflows ??= [];
6299
+ source.triggers.workflows.push(target.id);
6300
+ } else {
6301
+ source.triggers.agents ??= [];
6302
+ source.triggers.agents.push(target.id);
6303
+ }
6304
+ continue;
6305
+ }
6306
+ if (relationship.kind === "uses" && relationship.from.kind === "resource" && relationship.to.kind === "resource") {
6307
+ const target = model.resources[relationship.to.id];
6308
+ if (target?.kind !== "integration") continue;
6309
+ const source = ensure(relationship.from.id);
6310
+ source.uses ??= {};
6311
+ source.uses.integrations ??= [];
6312
+ source.uses.integrations.push(target.id);
6313
+ }
8154
6314
  }
8155
- return (deal.ownership ?? getDealOwnership(deal)) === "us";
6315
+ return projected;
6316
+ }
6317
+ function projectDeploymentSpec(options) {
6318
+ const workflows = withPlatformResourceDescriptors(
6319
+ options.workflows,
6320
+ options.getWorkflowResourceDescriptor,
6321
+ options.getResourceOntologyBinding
6322
+ );
6323
+ const integrations = withPlatformIntegrationResourceDescriptors(
6324
+ options.integrations ?? [],
6325
+ options.getIntegrationResourceDescriptor,
6326
+ options.getResourceOntologyBinding
6327
+ );
6328
+ const workflowResourceIds = new Set(workflows.map((workflow) => workflow.config.resourceId));
6329
+ const integrationResourceIds = new Set(integrations.map((integration) => integration.resourceId));
6330
+ const resources = projectDeploymentResources(
6331
+ options.organizationModel.resources,
6332
+ workflowResourceIds,
6333
+ integrationResourceIds,
6334
+ options.getResourceOntologyBinding
6335
+ );
6336
+ return {
6337
+ version: options.version,
6338
+ organizationModel: {
6339
+ systems: projectDeploymentSystems(options.organizationModel),
6340
+ resources
6341
+ },
6342
+ workflows,
6343
+ agents: options.agents ?? [],
6344
+ triggers: options.triggers,
6345
+ integrations,
6346
+ humanCheckpoints: options.humanCheckpoints,
6347
+ relationships: projectTopologyRelationships(options.organizationModel),
6348
+ ...options.externalResources ? { externalResources: options.externalResources } : {}
6349
+ };
6350
+ }
6351
+ function projectDeploymentResources(resources, workflowResourceIds, integrationResourceIds, getResourceOntologyBinding) {
6352
+ return Object.fromEntries(
6353
+ Object.values(resources).filter((resource) => workflowResourceIds.has(resource.id) || integrationResourceIds.has(resource.id)).map((resource) => {
6354
+ const sdkResource = toSdkResourceDescriptor(resource, getResourceOntologyBinding);
6355
+ return [sdkResource.id, sdkResource];
6356
+ })
6357
+ );
6358
+ }
6359
+ function projectDeploymentSystems(model) {
6360
+ return Object.fromEntries(
6361
+ listAllSystems(model).map(({ path, system }, index) => {
6362
+ const lifecycle = system.lifecycle === "archived" ? "archived" : system.lifecycle === "deprecated" ? "deprecated" : "active";
6363
+ return [
6364
+ system.id,
6365
+ {
6366
+ id: system.id,
6367
+ order: system.order ?? (index + 1) * 10,
6368
+ title: system.label ?? system.title ?? system.id,
6369
+ description: system.description ?? "",
6370
+ kind: system.kind ?? "product",
6371
+ ...system.parentSystemId ? { parentSystemId: system.parentSystemId } : {},
6372
+ ...path !== system.id ? { systemPath: path } : {},
6373
+ governedByKnowledge: system.governedByKnowledge ?? [],
6374
+ drivesGoals: system.drivesGoals ?? [],
6375
+ lifecycle,
6376
+ status: lifecycle,
6377
+ ...system.responsibleRoleId ? { responsibleRoleId: system.responsibleRoleId } : {}
6378
+ }
6379
+ ];
6380
+ })
6381
+ );
8156
6382
  }
8157
6383
  var ListBuilderStageKeySchema = z.string().min(1);
8158
6384
 
8159
- export { ActivityEventSchema, BuildPlanSnapshotStepSchema, ProspectingBuildTemplateSchema as BuildTemplateSchema, ContractRefResolutionError, CrmStageKeySchema, CrmStateKeySchema, DEFAULT_CRM_ACTIONS, EmailSchema, ExecutionError, ListBuilderStageKeySchema, ProcessingStageStatusSchema, RegistryValidationError, ResourceRegistry, StepType, ToolingError, bindResourceDescriptor, concurrentPool, defineContract, defineResource, defineResourceOntology, defineResources, defineStep, defineTopology, defineTopologyRelationship, defineWorkflow, deriveActions, diagnosticOutput, integrationInput, isZodType, parseTopologyNodeRef, resolveContractRef, runDiagnostic, splitName, topologyRef, topologyRelationship, validateResourceGovernance };
6385
+ export { ActivityEventSchema, BuildPlanSnapshotStepSchema, ProspectingBuildTemplateSchema as BuildTemplateSchema, ContractRefResolutionError, CrmStageKeySchema, CrmStateKeySchema, EmailSchema, ExecutionError, ListBuilderStageKeySchema, ProcessingStageStatusSchema, RegistryValidationError, ResourceRegistry, StepType, ToolingError, bindResourceDescriptor, compileBusinessOntologyValidationIndex, concurrentPool, createLeadGenStageValidators, defineContract, defineResource, defineResourceOntology, defineResources, defineStep, defineTopology, defineTopologyRelationship, defineWorkflow, deriveActions, diagnosticOutput, integrationInput, isZodType, parseTopologyNodeRef, projectDeploymentSpec, projectTopologyRelationships, resolveContractRef, runDiagnostic, splitName, toSdkResourceDescriptor, topologyRef, topologyRelationship, validateResourceGovernance, withPlatformIntegrationResourceDescriptor, withPlatformIntegrationResourceDescriptors, withPlatformResourceDescriptor, withPlatformResourceDescriptors };