@elevasis/core 0.25.0 → 0.27.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 (80) hide show
  1. package/dist/index.d.ts +171 -90
  2. package/dist/index.js +377 -1541
  3. package/dist/knowledge/index.d.ts +48 -59
  4. package/dist/knowledge/index.js +1 -1
  5. package/dist/organization-model/index.d.ts +171 -90
  6. package/dist/organization-model/index.js +377 -1541
  7. package/dist/test-utils/index.d.ts +25 -33
  8. package/dist/test-utils/index.js +250 -1357
  9. package/package.json +1 -1
  10. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +990 -1065
  11. package/src/business/acquisition/api-schemas.test.ts +1996 -1882
  12. package/src/business/acquisition/api-schemas.ts +1478 -1502
  13. package/src/business/acquisition/crm-next-action.test.ts +45 -25
  14. package/src/business/acquisition/crm-next-action.ts +227 -220
  15. package/src/business/acquisition/crm-priority.test.ts +41 -8
  16. package/src/business/acquisition/crm-priority.ts +365 -349
  17. package/src/business/acquisition/crm-state-actions.test.ts +208 -153
  18. package/src/business/acquisition/derive-actions.test.ts +101 -34
  19. package/src/business/acquisition/derive-actions.ts +8 -92
  20. package/src/business/acquisition/ontology-validation.ts +76 -162
  21. package/src/business/acquisition/types.ts +7 -8
  22. package/src/business/pdf/sections/investment.ts +1 -1
  23. package/src/business/pdf/sections/summary-investment.ts +1 -1
  24. package/src/execution/engine/tools/tool-maps.ts +872 -831
  25. package/src/knowledge/queries.ts +0 -1
  26. package/src/organization-model/__tests__/content-kinds-registry.test.ts +35 -210
  27. package/src/organization-model/__tests__/cross-ref.test.ts +167 -0
  28. package/src/organization-model/__tests__/defaults.test.ts +4 -4
  29. package/src/organization-model/__tests__/domains/actions.test.ts +12 -36
  30. package/src/organization-model/__tests__/domains/offerings.test.ts +13 -6
  31. package/src/organization-model/__tests__/domains/resources.test.ts +497 -350
  32. package/src/organization-model/__tests__/domains/systems.test.ts +6 -7
  33. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +68 -80
  34. package/src/organization-model/__tests__/foundation.test.ts +81 -14
  35. package/src/organization-model/__tests__/graph.test.ts +662 -694
  36. package/src/organization-model/__tests__/knowledge.test.ts +31 -17
  37. package/src/organization-model/__tests__/lookup-helpers.test.ts +128 -438
  38. package/src/organization-model/__tests__/migration-helpers.test.ts +362 -591
  39. package/src/organization-model/__tests__/prospecting-ssot.test.ts +68 -103
  40. package/src/organization-model/__tests__/published-zero-leak.test.ts +76 -0
  41. package/src/organization-model/__tests__/recursive-system-schema.test.ts +159 -532
  42. package/src/organization-model/__tests__/resolve.test.ts +79 -42
  43. package/src/organization-model/__tests__/schema-refinements.test.ts +72 -0
  44. package/src/organization-model/__tests__/schema.test.ts +65 -56
  45. package/src/organization-model/catalogs/lead-gen.ts +0 -103
  46. package/src/organization-model/cross-ref.ts +175 -0
  47. package/src/organization-model/defaults.ts +17 -702
  48. package/src/organization-model/domains/actions.ts +116 -333
  49. package/src/organization-model/domains/branding.ts +6 -6
  50. package/src/organization-model/domains/knowledge.ts +15 -7
  51. package/src/organization-model/domains/projects.ts +4 -4
  52. package/src/organization-model/domains/prospecting.ts +405 -395
  53. package/src/organization-model/domains/resources.ts +206 -135
  54. package/src/organization-model/domains/sales.test.ts +104 -218
  55. package/src/organization-model/domains/sales.ts +217 -380
  56. package/src/organization-model/domains/systems.ts +8 -23
  57. package/src/organization-model/graph/build.ts +223 -294
  58. package/src/organization-model/graph/schema.ts +2 -3
  59. package/src/organization-model/graph/types.ts +12 -14
  60. package/src/organization-model/helpers.ts +130 -218
  61. package/src/organization-model/index.ts +105 -124
  62. package/src/organization-model/migration-helpers.ts +211 -249
  63. package/src/organization-model/ontology.ts +0 -60
  64. package/src/organization-model/organization-graph.mdx +4 -5
  65. package/src/organization-model/organization-model.mdx +1 -1
  66. package/src/organization-model/published.ts +236 -226
  67. package/src/organization-model/resolve.ts +4 -5
  68. package/src/organization-model/schema-refinements.ts +667 -0
  69. package/src/organization-model/schema.ts +88 -889
  70. package/src/organization-model/types.ts +167 -161
  71. package/src/platform/registry/__tests__/validation.test.ts +23 -0
  72. package/src/platform/registry/validation.ts +13 -2
  73. package/src/reference/_generated/contracts.md +990 -1065
  74. package/src/organization-model/content-kinds/config.ts +0 -36
  75. package/src/organization-model/content-kinds/index.ts +0 -78
  76. package/src/organization-model/content-kinds/pipeline.ts +0 -68
  77. package/src/organization-model/content-kinds/registry.ts +0 -44
  78. package/src/organization-model/content-kinds/status.ts +0 -71
  79. package/src/organization-model/content-kinds/template.ts +0 -83
  80. package/src/organization-model/content-kinds/types.ts +0 -117
@@ -1,333 +1,116 @@
1
- import { z } from 'zod'
2
- import { EntityIdSchema } from './entities'
3
- import { DescriptionSchema, LabelSchema, ModelIdSchema } from './shared'
4
-
5
- export const ActionResourceIdSchema = z
6
- .string()
7
- .trim()
8
- .min(1)
9
- .max(255)
10
- .regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, 'Resource IDs must use letters, numbers, -, _, or . separators')
11
-
12
- export const ActionInvocationKindSchema = z
13
- .enum(['slash-command', 'mcp-tool', 'api-endpoint', 'script-execution'])
14
- .meta({ label: 'Invocation kind' })
15
-
16
- export const ActionIdSchema = ModelIdSchema
17
-
18
- export const ActionScopeSchema = z.union([
19
- z.literal('global'),
20
- z.object({
21
- domain: ModelIdSchema
22
- })
23
- ])
24
-
25
- export const ActionRefSchema = z.object({
26
- actionId: ActionIdSchema.meta({ ref: 'action' }),
27
- intent: z.enum(['exposes', 'consumes']).meta({ label: 'Intent' })
28
- })
29
-
30
- export const SlashCommandInvocationSchema = z.object({
31
- kind: z.literal('slash-command'),
32
- command: z
33
- .string()
34
- .trim()
35
- .min(1)
36
- .max(200)
37
- .regex(/^\/[^\s].*$/, 'Slash commands must start with /'),
38
- toolFactory: ModelIdSchema.optional()
39
- })
40
-
41
- export const McpToolInvocationSchema = z.object({
42
- kind: z.literal('mcp-tool'),
43
- server: ModelIdSchema,
44
- name: ModelIdSchema
45
- })
46
-
47
- export const ApiEndpointInvocationSchema = z.object({
48
- kind: z.literal('api-endpoint'),
49
- method: z.enum(['GET', 'POST', 'PATCH', 'DELETE']).meta({ label: 'HTTP method' }),
50
- path: z.string().trim().startsWith('/').max(500),
51
- requestSchema: ModelIdSchema.optional(),
52
- responseSchema: ModelIdSchema.optional()
53
- })
54
-
55
- export const ScriptExecutionInvocationSchema = z.object({
56
- kind: z.literal('script-execution'),
57
- resourceId: ActionResourceIdSchema
58
- })
59
-
60
- export const ActionInvocationSchema = z.discriminatedUnion('kind', [
61
- SlashCommandInvocationSchema,
62
- McpToolInvocationSchema,
63
- ApiEndpointInvocationSchema,
64
- ScriptExecutionInvocationSchema
65
- ])
66
-
67
- export const ActionSchema = z.object({
68
- id: ActionIdSchema,
69
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
70
- order: z.number(),
71
- label: LabelSchema,
72
- description: DescriptionSchema.optional(),
73
- scope: ActionScopeSchema.default('global'),
74
- resourceId: ActionResourceIdSchema.optional(),
75
- affects: z.array(EntityIdSchema.meta({ ref: 'entity' })).optional(),
76
- invocations: z.array(ActionInvocationSchema).default([]),
77
- knowledge: z
78
- .array(ModelIdSchema.meta({ ref: 'knowledge' }))
79
- .default([])
80
- .optional(),
81
- lifecycle: z
82
- .enum(['draft', 'beta', 'active', 'deprecated', 'archived'])
83
- .meta({ label: 'Lifecycle', color: 'teal' })
84
- .default('active')
85
- })
86
-
87
- export const ActionsDomainSchema = z
88
- .record(z.string(), ActionSchema)
89
- .refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
90
- message: 'Each action entry id must match its map key'
91
- })
92
- .default({})
93
-
94
- const LEAD_GEN_ACTION_ENTRY_INPUTS: z.input<typeof ActionSchema>[] = [
95
- {
96
- id: 'lead-gen.company.source',
97
- order: 10,
98
- label: 'Source companies',
99
- description: 'Import source companies from a list provider.',
100
- scope: { domain: 'sales' },
101
- resourceId: 'lgn-import-workflow',
102
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/companies/source' }]
103
- },
104
- {
105
- id: 'lead-gen.company.apollo-import',
106
- order: 20,
107
- label: 'Import from Apollo',
108
- description: 'Pull companies and seed contact data from an Apollo search or list.',
109
- scope: { domain: 'sales' },
110
- resourceId: 'lgn-01c-apollo-import-workflow',
111
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/companies/apollo-import' }]
112
- },
113
- {
114
- id: 'lead-gen.contact.discover',
115
- order: 30,
116
- label: 'Discover contact emails',
117
- description: 'Find email addresses for contacts at qualified companies.',
118
- scope: { domain: 'sales' },
119
- resourceId: 'lgn-04-email-discovery-workflow',
120
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/contacts/discover' }]
121
- },
122
- {
123
- id: 'lead-gen.contact.verify-email',
124
- order: 40,
125
- label: 'Verify emails',
126
- description: 'Check email deliverability before outreach.',
127
- scope: { domain: 'sales' },
128
- resourceId: 'lgn-05-email-verification-workflow',
129
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/contacts/verify-email' }]
130
- },
131
- {
132
- id: 'lead-gen.company.apify-crawl',
133
- order: 50,
134
- label: 'Crawl websites',
135
- description:
136
- 'Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.',
137
- scope: { domain: 'sales' },
138
- resourceId: 'lgn-02a-apify-website-crawl-workflow',
139
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/companies/apify-crawl' }]
140
- },
141
- {
142
- id: 'lead-gen.company.website-extract',
143
- order: 60,
144
- label: 'Extract website signals',
145
- description: 'Scrape and analyze company websites for qualification signals.',
146
- scope: { domain: 'sales' },
147
- resourceId: 'lgn-02-website-extract-workflow',
148
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/companies/website-extract' }]
149
- },
150
- {
151
- id: 'lead-gen.company.qualify',
152
- order: 70,
153
- label: 'Qualify companies',
154
- description: 'Score and filter companies against the ICP rubric.',
155
- scope: { domain: 'sales' },
156
- resourceId: 'lgn-03-company-qualification-workflow',
157
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/companies/qualify' }]
158
- },
159
- {
160
- id: 'lead-gen.company.dtc-subscription-qualify',
161
- order: 80,
162
- label: 'Qualify DTC subscription fit',
163
- description: 'Classify subscription potential and consumable-product fit for DTC brands.',
164
- scope: { domain: 'sales' },
165
- resourceId: 'lgn-03b-dtc-subscription-score-workflow',
166
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/companies/dtc-subscription-qualify' }]
167
- },
168
- {
169
- id: 'lead-gen.contact.apollo-decision-maker-enrich',
170
- order: 90,
171
- label: 'Enrich decision-makers',
172
- description: 'Find and enrich qualified contacts at qualified companies via Apollo.',
173
- scope: { domain: 'sales' },
174
- resourceId: 'lgn-04b-apollo-decision-maker-enrich-workflow',
175
- invocations: [
176
- { kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/contacts/apollo-decision-maker-enrich' }
177
- ]
178
- },
179
- {
180
- id: 'lead-gen.contact.personalize',
181
- order: 100,
182
- label: 'Personalize outreach',
183
- description: 'Generate personalized opening lines for each contact.',
184
- scope: { domain: 'sales' },
185
- resourceId: 'ist-personalization-workflow',
186
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/contacts/personalize' }]
187
- },
188
- {
189
- id: 'lead-gen.review.outreach-ready',
190
- order: 110,
191
- label: 'Upload to outreach',
192
- description: 'Upload approved contacts to the outreach sequence after QC review.',
193
- scope: { domain: 'sales' },
194
- resourceId: 'ist-upload-contacts-workflow',
195
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/review/outreach-ready' }]
196
- },
197
- {
198
- id: 'lead-gen.export.list',
199
- order: 120,
200
- label: 'Export lead list',
201
- description: 'Export approved leads as a downloadable lead list.',
202
- scope: { domain: 'sales' },
203
- resourceId: 'lgn-06-export-list-workflow',
204
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/export/list' }]
205
- },
206
- {
207
- id: 'lead-gen.company.cleanup',
208
- order: 130,
209
- label: 'Clean up companies',
210
- description: 'Remove disqualified or duplicate companies from the list.',
211
- scope: { domain: 'sales' },
212
- resourceId: 'lgn-company-cleanup-workflow',
213
- invocations: [{ kind: 'api-endpoint', method: 'POST', path: '/api/prospecting/companies/cleanup' }]
214
- }
215
- ]
216
-
217
- export const LEAD_GEN_ACTION_ENTRIES: Record<string, z.infer<typeof ActionSchema>> = Object.fromEntries(
218
- LEAD_GEN_ACTION_ENTRY_INPUTS.map((action) => {
219
- const parsed = ActionSchema.parse(action)
220
- return [parsed.id, parsed]
221
- })
222
- )
223
-
224
- const CRM_ACTION_ENTRY_INPUTS: z.input<typeof ActionSchema>[] = [
225
- {
226
- id: 'send_reply',
227
- order: 210,
228
- label: 'Send Reply',
229
- description: 'Send a contextual reply for an active CRM deal.',
230
- scope: { domain: 'sales' },
231
- resourceId: 'crm-send-reply-workflow',
232
- affects: ['crm.deal']
233
- },
234
- {
235
- id: 'send_link',
236
- order: 220,
237
- label: 'Send Booking Link',
238
- description: 'Send a booking link to move a deal toward a scheduled call.',
239
- scope: { domain: 'sales' },
240
- resourceId: 'crm-send-booking-link-workflow',
241
- affects: ['crm.deal']
242
- },
243
- {
244
- id: 'send_nudge',
245
- order: 230,
246
- label: 'Send Nudge',
247
- description: 'Send a follow-up nudge for a stalled CRM deal.',
248
- scope: { domain: 'sales' },
249
- resourceId: 'crm-send-nudge-workflow',
250
- affects: ['crm.deal']
251
- },
252
- {
253
- id: 'rebook',
254
- order: 240,
255
- label: 'Rebook',
256
- description: 'Rebook a missed or rescheduled CRM appointment.',
257
- scope: { domain: 'sales' },
258
- resourceId: 'crm-rebook-workflow',
259
- affects: ['crm.deal']
260
- },
261
- {
262
- id: 'move_to_proposal',
263
- order: 250,
264
- label: 'Move to Proposal',
265
- description: 'Advance a qualified CRM deal into the proposal stage.',
266
- scope: { domain: 'sales' },
267
- resourceId: 'move_to_proposal-workflow',
268
- affects: ['crm.deal']
269
- },
270
- {
271
- id: 'move_to_closing',
272
- order: 260,
273
- label: 'Move to Closing',
274
- description: 'Advance a proposal-stage CRM deal into closing.',
275
- scope: { domain: 'sales' },
276
- resourceId: 'move_to_closing-workflow',
277
- affects: ['crm.deal']
278
- },
279
- {
280
- id: 'move_to_closed_won',
281
- order: 270,
282
- label: 'Close Won',
283
- description: 'Mark a CRM deal as closed won.',
284
- scope: { domain: 'sales' },
285
- resourceId: 'move_to_closed_won-workflow',
286
- affects: ['crm.deal']
287
- },
288
- {
289
- id: 'move_to_closed_lost',
290
- order: 280,
291
- label: 'Close Lost',
292
- description: 'Mark a CRM deal as closed lost.',
293
- scope: { domain: 'sales' },
294
- resourceId: 'move_to_closed_lost-workflow',
295
- affects: ['crm.deal']
296
- },
297
- {
298
- id: 'move_to_nurturing',
299
- order: 290,
300
- label: 'Move to Nurturing',
301
- description: 'Move a CRM deal into nurturing for future follow-up.',
302
- scope: { domain: 'sales' },
303
- resourceId: 'move_to_nurturing-workflow',
304
- affects: ['crm.deal']
305
- }
306
- ]
307
-
308
- export const CRM_ACTION_ENTRIES: Record<string, z.infer<typeof ActionSchema>> = Object.fromEntries(
309
- CRM_ACTION_ENTRY_INPUTS.map((action) => {
310
- const parsed = ActionSchema.parse(action)
311
- return [parsed.id, parsed]
312
- })
313
- )
314
-
315
- export const DEFAULT_ORGANIZATION_MODEL_ACTIONS: z.infer<typeof ActionsDomainSchema> = {
316
- ...LEAD_GEN_ACTION_ENTRIES,
317
- ...CRM_ACTION_ENTRIES
318
- }
319
-
320
- export function findOrganizationActionById(
321
- id: string,
322
- actions: z.infer<typeof ActionsDomainSchema> = DEFAULT_ORGANIZATION_MODEL_ACTIONS
323
- ): z.infer<typeof ActionSchema> | undefined {
324
- return actions[id]
325
- }
326
-
327
- export type ActionId = z.infer<typeof ActionIdSchema>
328
- export type ActionScope = z.infer<typeof ActionScopeSchema>
329
- export type ActionRef = z.infer<typeof ActionRefSchema>
330
- export type ActionInvocationKind = z.infer<typeof ActionInvocationKindSchema>
331
- export type ActionInvocation = z.infer<typeof ActionInvocationSchema>
332
- export type Action = z.infer<typeof ActionSchema>
333
- export type ActionsDomain = z.infer<typeof ActionsDomainSchema>
1
+ import { z } from 'zod'
2
+ import { EntityIdSchema } from './entities'
3
+ import { DescriptionSchema, LabelSchema, ModelIdSchema } from './shared'
4
+
5
+ export const ActionResourceIdSchema = z
6
+ .string()
7
+ .trim()
8
+ .min(1)
9
+ .max(255)
10
+ .regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, 'Resource IDs must use letters, numbers, -, _, or . separators')
11
+
12
+ export const ActionInvocationKindSchema = z
13
+ .enum(['slash-command', 'mcp-tool', 'api-endpoint', 'script-execution'])
14
+ .meta({ label: 'Invocation kind' })
15
+
16
+ export const ActionIdSchema = ModelIdSchema
17
+
18
+ export const ActionScopeSchema = z.union([
19
+ z.literal('global'),
20
+ z.object({
21
+ domain: ModelIdSchema
22
+ })
23
+ ])
24
+
25
+ export const ActionRefSchema = z.object({
26
+ actionId: ActionIdSchema.meta({ ref: 'action' }),
27
+ intent: z.enum(['exposes', 'consumes']).meta({ label: 'Intent' })
28
+ })
29
+
30
+ export const SlashCommandInvocationSchema = z.object({
31
+ kind: z.literal('slash-command'),
32
+ command: z
33
+ .string()
34
+ .trim()
35
+ .min(1)
36
+ .max(200)
37
+ .regex(/^\/[^\s].*$/, 'Slash commands must start with /'),
38
+ toolFactory: ModelIdSchema.optional()
39
+ })
40
+
41
+ export const McpToolInvocationSchema = z.object({
42
+ kind: z.literal('mcp-tool'),
43
+ server: ModelIdSchema,
44
+ name: ModelIdSchema
45
+ })
46
+
47
+ export const ApiEndpointInvocationSchema = z.object({
48
+ kind: z.literal('api-endpoint'),
49
+ method: z.enum(['GET', 'POST', 'PATCH', 'DELETE']).meta({ label: 'HTTP method' }),
50
+ path: z.string().trim().startsWith('/').max(500),
51
+ requestSchema: ModelIdSchema.optional(),
52
+ responseSchema: ModelIdSchema.optional()
53
+ })
54
+
55
+ export const ScriptExecutionInvocationSchema = z.object({
56
+ kind: z.literal('script-execution'),
57
+ resourceId: ActionResourceIdSchema
58
+ })
59
+
60
+ export const ActionInvocationSchema = z.discriminatedUnion('kind', [
61
+ SlashCommandInvocationSchema,
62
+ McpToolInvocationSchema,
63
+ ApiEndpointInvocationSchema,
64
+ ScriptExecutionInvocationSchema
65
+ ])
66
+
67
+ export const ActionSchema = z.object({
68
+ id: ActionIdSchema,
69
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
70
+ order: z.number(),
71
+ label: LabelSchema,
72
+ description: DescriptionSchema.optional(),
73
+ scope: ActionScopeSchema.default('global'),
74
+ resourceId: ActionResourceIdSchema.optional(),
75
+ affects: z.array(EntityIdSchema.meta({ ref: 'entity' })).optional(),
76
+ invocations: z.array(ActionInvocationSchema).default([]),
77
+ knowledge: z
78
+ .array(ModelIdSchema.meta({ ref: 'knowledge' }))
79
+ .default([])
80
+ .optional(),
81
+ lifecycle: z
82
+ .enum(['draft', 'beta', 'active', 'deprecated', 'archived'])
83
+ .meta({ label: 'Lifecycle', color: 'teal' })
84
+ .default('active')
85
+ })
86
+
87
+ export const ActionsDomainSchema = z
88
+ .record(z.string(), ActionSchema)
89
+ .refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
90
+ message: 'Each action entry id must match its map key'
91
+ })
92
+ .default({})
93
+
94
+ /**
95
+ * Generic empty default for the actions domain.
96
+ * Elevasis-specific action entries (LEAD_GEN_ACTION_ENTRIES, CRM_ACTION_ENTRIES,
97
+ * DEFAULT_ORGANIZATION_MODEL_ACTIONS) have been relocated to
98
+ * `@repo/elevasis-core/src/organization-model/actions.ts`.
99
+ * Tenant OM configs supply their own action entries via `resolveOrganizationModel`.
100
+ */
101
+ export const DEFAULT_ORGANIZATION_MODEL_ACTIONS: z.infer<typeof ActionsDomainSchema> = {}
102
+
103
+ export function findOrganizationActionById(
104
+ id: string,
105
+ actions: z.infer<typeof ActionsDomainSchema> = DEFAULT_ORGANIZATION_MODEL_ACTIONS
106
+ ): z.infer<typeof ActionSchema> | undefined {
107
+ return actions[id]
108
+ }
109
+
110
+ export type ActionId = z.infer<typeof ActionIdSchema>
111
+ export type ActionScope = z.infer<typeof ActionScopeSchema>
112
+ export type ActionRef = z.infer<typeof ActionRefSchema>
113
+ export type ActionInvocationKind = z.infer<typeof ActionInvocationKindSchema>
114
+ export type ActionInvocation = z.infer<typeof ActionInvocationSchema>
115
+ export type Action = z.infer<typeof ActionSchema>
116
+ export type ActionsDomain = z.infer<typeof ActionsDomainSchema>
@@ -14,9 +14,9 @@ export const OrganizationModelBrandingSchema = z.object({
14
14
  .default({})
15
15
  })
16
16
 
17
- export const DEFAULT_ORGANIZATION_MODEL_BRANDING: z.infer<typeof OrganizationModelBrandingSchema> = {
18
- organizationName: 'Default Organization',
19
- productName: 'Elevasis',
20
- shortName: 'Elevasis',
21
- logos: {}
22
- }
17
+ export const DEFAULT_ORGANIZATION_MODEL_BRANDING: z.infer<typeof OrganizationModelBrandingSchema> = {
18
+ organizationName: 'Default Organization',
19
+ productName: 'Organization OS',
20
+ shortName: 'Org OS',
21
+ logos: {}
22
+ }
@@ -21,16 +21,13 @@ export const KnowledgeTargetKindSchema = z
21
21
  'goal',
22
22
  'customer-segment',
23
23
  'offering',
24
- 'ontology',
25
- // D4: content nodes are a valid knowledge target after compound-domain data moved into system.content
26
- 'content-node'
24
+ 'ontology'
27
25
  ])
28
26
  .meta({ label: 'Target kind' })
29
27
 
30
28
  export const KnowledgeTargetRefSchema = z
31
29
  .object({
32
30
  kind: KnowledgeTargetKindSchema,
33
- // D4: content-node targets use a qualified id format '<system-path>:<local-content-id>'.
34
31
  // Ontology targets use the canonical '<scope>:<kind>/<local-id>' ontology id format.
35
32
  // Business-logic validation of target existence is done in OrganizationModelSchema.superRefine.
36
33
  id: z.string().trim().min(1).max(300)
@@ -48,9 +45,20 @@ export const KnowledgeTargetRefSchema = z
48
45
  }
49
46
  })
50
47
 
51
- const LegacyKnowledgeLinkSchema = z.object({
52
- nodeId: z.union([NodeIdStringSchema, z.templateLiteral(['ontology:', OntologyIdSchema])])
53
- })
48
+ const LegacyKnowledgeLinkSchema = z
49
+ .object({
50
+ nodeId: z.union([NodeIdStringSchema, z.templateLiteral(['ontology:', OntologyIdSchema])])
51
+ })
52
+ .superRefine((link, ctx) => {
53
+ const [kind] = link.nodeId.split(':')
54
+ if (!KnowledgeTargetKindSchema.safeParse(kind).success) {
55
+ ctx.addIssue({
56
+ code: z.ZodIssueCode.custom,
57
+ path: ['nodeId'],
58
+ message: `Unknown knowledge target kind "${kind}"`
59
+ })
60
+ }
61
+ })
54
62
 
55
63
  const CanonicalKnowledgeLinkSchema = z.object({
56
64
  target: KnowledgeTargetRefSchema
@@ -6,9 +6,9 @@ export const ProjectsDomainStateSchema = DisplayMetadataSchema.extend({
6
6
  order: z.number().int().min(0)
7
7
  })
8
8
 
9
- // Phase 4 cut: OrganizationModelProjectsSchema and DEFAULT_ORGANIZATION_MODEL_PROJECTS removed.
10
- // Project/milestone/task status data moved into system.content as (schema:status-flow) and
11
- // (schema:status) content nodes on the owning system. Use getAllProjectStatuses() from
12
- // migration-helpers to read status data portably.
9
+ // OrganizationModelProjectsSchema and DEFAULT_ORGANIZATION_MODEL_PROJECTS are retired.
10
+ // Project/milestone/task status data lives in System.ontology.catalogTypes on
11
+ // the owning system. Use getAllProjectStatuses() from migration-helpers to read
12
+ // status data portably.
13
13
  //
14
14
  // ProjectsDomainStateSchema is retained as the payload shape type for individual status entries.