@elevasis/core 0.24.1 → 0.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 (82) hide show
  1. package/dist/index.d.ts +239 -86
  2. package/dist/index.js +474 -1346
  3. package/dist/knowledge/index.d.ts +57 -39
  4. package/dist/knowledge/index.js +1 -1
  5. package/dist/organization-model/index.d.ts +239 -86
  6. package/dist/organization-model/index.js +474 -1346
  7. package/dist/test-utils/index.d.ts +24 -31
  8. package/dist/test-utils/index.js +76 -1238
  9. package/package.json +1 -1
  10. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +108 -96
  11. package/src/business/acquisition/api-schemas.test.ts +70 -77
  12. package/src/business/acquisition/api-schemas.ts +21 -42
  13. package/src/business/acquisition/derive-actions.test.ts +11 -21
  14. package/src/business/acquisition/derive-actions.ts +61 -14
  15. package/src/business/acquisition/ontology-validation.ts +4 -4
  16. package/src/business/acquisition/types.ts +7 -8
  17. package/src/execution/engine/llm/adapters/__tests__/openrouter.integration.test.ts +10 -10
  18. package/src/knowledge/__tests__/queries.test.ts +960 -546
  19. package/src/knowledge/format.ts +322 -100
  20. package/src/knowledge/index.ts +18 -5
  21. package/src/knowledge/queries.ts +1004 -240
  22. package/src/organization-model/__tests__/content-kinds-registry.test.ts +35 -210
  23. package/src/organization-model/__tests__/defaults.test.ts +4 -4
  24. package/src/organization-model/__tests__/deprecate-helpers.test.ts +71 -0
  25. package/src/organization-model/__tests__/domains/actions.test.ts +12 -36
  26. package/src/organization-model/__tests__/domains/offerings.test.ts +13 -6
  27. package/src/organization-model/__tests__/domains/resources.test.ts +497 -350
  28. package/src/organization-model/__tests__/domains/systems.test.ts +6 -7
  29. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +68 -80
  30. package/src/organization-model/__tests__/foundation.test.ts +81 -14
  31. package/src/organization-model/__tests__/graph.test.ts +662 -694
  32. package/src/organization-model/__tests__/knowledge.test.ts +31 -17
  33. package/src/organization-model/__tests__/lookup-helpers.test.ts +128 -438
  34. package/src/organization-model/__tests__/migration-helpers.test.ts +362 -591
  35. package/src/organization-model/__tests__/prospecting-ssot.test.ts +68 -103
  36. package/src/organization-model/__tests__/published-zero-leak.test.ts +17 -0
  37. package/src/organization-model/__tests__/recursive-system-schema.test.ts +159 -532
  38. package/src/organization-model/__tests__/resolve.test.ts +88 -49
  39. package/src/organization-model/__tests__/scaffolders.test.ts +93 -0
  40. package/src/organization-model/__tests__/schema.test.ts +65 -56
  41. package/src/organization-model/catalogs/lead-gen.ts +0 -103
  42. package/src/organization-model/defaults.ts +17 -702
  43. package/src/organization-model/domains/actions.ts +116 -333
  44. package/src/organization-model/domains/knowledge.ts +15 -7
  45. package/src/organization-model/domains/projects.ts +4 -4
  46. package/src/organization-model/domains/prospecting.ts +405 -395
  47. package/src/organization-model/domains/resources.ts +206 -135
  48. package/src/organization-model/domains/sales.ts +5 -5
  49. package/src/organization-model/domains/systems.ts +8 -23
  50. package/src/organization-model/graph/build.ts +223 -294
  51. package/src/organization-model/graph/schema.ts +2 -3
  52. package/src/organization-model/graph/types.ts +12 -14
  53. package/src/organization-model/helpers.ts +120 -141
  54. package/src/organization-model/icons.ts +1 -0
  55. package/src/organization-model/index.ts +107 -126
  56. package/src/organization-model/migration-helpers.ts +211 -249
  57. package/src/organization-model/ontology.ts +0 -60
  58. package/src/organization-model/organization-graph.mdx +4 -5
  59. package/src/organization-model/organization-model.mdx +1 -1
  60. package/src/organization-model/published.ts +251 -228
  61. package/src/organization-model/resolve.ts +4 -5
  62. package/src/organization-model/scaffolders/helpers.ts +84 -0
  63. package/src/organization-model/scaffolders/index.ts +19 -0
  64. package/src/organization-model/scaffolders/scaffoldKnowledgeNode.ts +48 -0
  65. package/src/organization-model/scaffolders/scaffoldOntologyRecord.ts +38 -0
  66. package/src/organization-model/scaffolders/scaffoldResource.ts +59 -0
  67. package/src/organization-model/scaffolders/scaffoldSystem.ts +110 -0
  68. package/src/organization-model/scaffolders/types.ts +81 -0
  69. package/src/organization-model/schema.ts +610 -704
  70. package/src/organization-model/types.ts +167 -161
  71. package/src/platform/constants/versions.ts +1 -1
  72. package/src/platform/registry/__tests__/validation.test.ts +23 -0
  73. package/src/platform/registry/validation.ts +13 -2
  74. package/src/reference/_generated/contracts.md +108 -96
  75. package/src/reference/glossary.md +71 -69
  76. package/src/organization-model/content-kinds/config.ts +0 -36
  77. package/src/organization-model/content-kinds/index.ts +0 -78
  78. package/src/organization-model/content-kinds/pipeline.ts +0 -68
  79. package/src/organization-model/content-kinds/registry.ts +0 -44
  80. package/src/organization-model/content-kinds/status.ts +0 -71
  81. package/src/organization-model/content-kinds/template.ts +0 -83
  82. package/src/organization-model/content-kinds/types.ts +0 -117
@@ -1,36 +1,38 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { ZodError } from 'zod'
3
- import { bindResourceDescriptor } from '../../../platform/registry/types'
4
- import {
5
- DEFAULT_ORGANIZATION_MODEL_RESOURCES,
6
- EventIdSchema,
1
+ import { describe, expect, it } from 'vitest'
2
+ import { ZodError } from 'zod'
3
+ import { bindResourceDescriptor } from '../../../platform/registry/types'
4
+ import {
5
+ ContractRefSchema,
6
+ DEFAULT_ORGANIZATION_MODEL_RESOURCES,
7
+ EventIdSchema,
7
8
  ResourceEntrySchema,
8
9
  ResourceKindSchema,
9
10
  ResourceOntologyBindingSchema,
10
11
  ResourcesDomainSchema,
11
- defineResource,
12
- defineResources
13
- } from '../../domains/resources'
14
- import { resolveOrganizationModel } from '../../resolve'
15
-
16
- const VALID_SYSTEM = {
17
- id: 'sys.lead-gen',
18
- order: 10,
19
- title: 'Lead Generation Pipeline',
20
- description: 'Coordinates prospecting, enrichment, qualification, and outreach preparation.',
21
- kind: 'operational' as const,
22
- status: 'active' as const
23
- }
24
-
25
- const VALID_ROLE = {
26
- id: 'role.sales-ops',
27
- order: 10,
28
- title: 'Sales Ops'
29
- }
30
-
31
- const WORKFLOW_RESOURCE = {
32
- id: 'LGN-01-company-scrape',
33
- order: 10,
12
+ defineResource,
13
+ defineResources,
14
+ parseContractRef
15
+ } from '../../domains/resources'
16
+ import { resolveOrganizationModel } from '../../resolve'
17
+
18
+ const VALID_SYSTEM = {
19
+ id: 'sys.lead-gen',
20
+ order: 10,
21
+ title: 'Lead Generation Pipeline',
22
+ description: 'Coordinates prospecting, enrichment, qualification, and outreach preparation.',
23
+ kind: 'operational' as const,
24
+ status: 'active' as const
25
+ }
26
+
27
+ const VALID_ROLE = {
28
+ id: 'role.sales-ops',
29
+ order: 10,
30
+ title: 'Sales Ops'
31
+ }
32
+
33
+ const WORKFLOW_RESOURCE = {
34
+ id: 'LGN-01-company-scrape',
35
+ order: 10,
34
36
  kind: 'workflow' as const,
35
37
  systemPath: 'sys.lead-gen',
36
38
  title: 'Company Scrape',
@@ -38,195 +40,195 @@ const WORKFLOW_RESOURCE = {
38
40
  ownerRoleId: 'role.sales-ops',
39
41
  status: 'active' as const,
40
42
  codeRefs: [
41
- {
42
- path: 'operations/src/lead-gen/company-scrape/index.ts',
43
- role: 'entrypoint' as const,
44
- symbol: 'companyScrapeWorkflow',
45
- description: 'Workflow definition bound to this OM resource descriptor.'
46
- }
47
- ]
48
- }
49
-
50
- const WORKFLOW_EVENT_EMISSION = {
51
- eventKey: 'processed',
52
- label: 'Processed',
53
- payloadSchema: 'leadgen.company.processed',
54
- lifecycle: 'active' as const
55
- }
56
-
57
- const AGENT_RESOURCE = {
58
- id: 'command-center-assistant',
59
- order: 20,
60
- kind: 'agent' as const,
61
- systemPath: 'sys.lead-gen',
62
- ownerRoleId: 'role.sales-ops',
63
- status: 'active' as const,
64
- agentKind: 'platform' as const,
65
- actsAsRoleId: 'role.sales-ops',
66
- sessionCapable: true,
67
- invocations: [{ kind: 'slash-command' as const, command: '/work handoff' }]
68
- }
69
-
70
- const INTEGRATION_RESOURCE = {
71
- id: 'attio-crm',
72
- order: 30,
73
- kind: 'integration' as const,
74
- systemPath: 'sys.lead-gen',
75
- ownerRoleId: 'role.sales-ops',
76
- status: 'active' as const,
77
- provider: 'attio'
78
- }
79
-
80
- const SCRIPT_RESOURCE = {
81
- id: 'leadgen-backfill-script',
82
- order: 40,
83
- kind: 'script' as const,
84
- systemPath: 'sys.lead-gen',
85
- ownerRoleId: 'role.sales-ops',
86
- status: 'active' as const,
87
- language: 'typescript' as const,
88
- source: {
89
- file: 'scripts/leadgen/backfill.ts'
90
- }
91
- }
92
-
93
- function resolveWithResources(resources: Record<string, unknown>) {
94
- return resolveOrganizationModel({
95
- roles: { 'role.sales-ops': VALID_ROLE },
96
- systems: { 'sys.lead-gen': VALID_SYSTEM },
97
- resources: resources as Record<string, typeof WORKFLOW_RESOURCE>
98
- })
99
- }
100
-
101
- describe('ResourceEntrySchema', () => {
102
- it('accepts workflow, agent, integration, and script descriptors with required systemPath', () => {
103
- expect(ResourceEntrySchema.safeParse(WORKFLOW_RESOURCE).success).toBe(true)
104
- expect(ResourceEntrySchema.safeParse(AGENT_RESOURCE).success).toBe(true)
105
- expect(ResourceEntrySchema.safeParse(INTEGRATION_RESOURCE).success).toBe(true)
106
- expect(ResourceEntrySchema.safeParse(SCRIPT_RESOURCE).success).toBe(true)
107
- })
108
-
109
- it('rejects resources without a systemPath', () => {
110
- const { systemPath: _systemPath, ...resourceWithoutSystem } = WORKFLOW_RESOURCE
111
-
112
- expect(ResourceEntrySchema.safeParse(resourceWithoutSystem).success).toBe(false)
113
- })
114
-
115
- it('defaults codeRefs and accepts resource-level implementation breadcrumbs', () => {
116
- const withCodeRefs = ResourceEntrySchema.safeParse(WORKFLOW_RESOURCE)
117
- const withoutCodeRefs = ResourceEntrySchema.safeParse({
118
- ...WORKFLOW_RESOURCE,
119
- codeRefs: undefined
120
- })
121
-
122
- expect(withCodeRefs.success).toBe(true)
123
- expect(withoutCodeRefs.success).toBe(true)
124
-
125
- if (withCodeRefs.success) {
126
- expect(withCodeRefs.data.codeRefs).toEqual(WORKFLOW_RESOURCE.codeRefs)
127
- }
128
- if (withoutCodeRefs.success) {
129
- expect(withoutCodeRefs.data.codeRefs).toEqual([])
130
- }
131
- })
132
-
133
- it('rejects codeRefs with an empty path', () => {
134
- expect(
135
- ResourceEntrySchema.safeParse({
136
- ...WORKFLOW_RESOURCE,
137
- codeRefs: [
138
- {
139
- path: ' ',
140
- role: 'entrypoint'
141
- }
142
- ]
143
- }).success
144
- ).toBe(false)
145
- })
146
-
147
- it('rejects codeRefs with an invalid role', () => {
148
- expect(
149
- ResourceEntrySchema.safeParse({
150
- ...WORKFLOW_RESOURCE,
151
- codeRefs: [
152
- {
153
- path: 'operations/src/lead-gen/company-scrape/index.ts',
154
- role: 'runtime'
155
- }
156
- ]
157
- }).success
158
- ).toBe(false)
159
- })
160
-
161
- it('rejects multi-system membership', () => {
162
- expect(
163
- ResourceEntrySchema.safeParse({
164
- ...WORKFLOW_RESOURCE,
165
- systemPath: ['sys.lead-gen', 'sys.crm']
166
- }).success
167
- ).toBe(false)
168
- })
169
-
170
- it('rejects an agent kind outside the code-side mirror enum', () => {
171
- expect(
172
- ResourceEntrySchema.safeParse({
173
- ...AGENT_RESOURCE,
174
- agentKind: 'runner'
175
- }).success
176
- ).toBe(false)
177
- })
178
-
179
- it('defaults agent invocations and accepts slash-command orchestration entries', () => {
180
- const result = ResourceEntrySchema.safeParse({
181
- ...AGENT_RESOURCE,
182
- invocations: undefined
183
- })
184
-
185
- expect(result.success).toBe(true)
186
- if (result.success) {
187
- expect(result.data.kind).toBe('agent')
188
- if (result.data.kind === 'agent') {
189
- expect(result.data.invocations).toEqual([])
190
- }
191
- }
192
-
193
- expect(ResourceEntrySchema.safeParse(AGENT_RESOURCE).success).toBe(true)
194
- })
195
-
196
- it('rejects malformed agent invocation entries', () => {
197
- expect(
198
- ResourceEntrySchema.safeParse({
199
- ...AGENT_RESOURCE,
200
- invocations: [{ kind: 'slash-command', command: 'work handoff' }]
201
- }).success
202
- ).toBe(false)
203
- })
204
-
43
+ {
44
+ path: 'operations/src/lead-gen/company-scrape/index.ts',
45
+ role: 'entrypoint' as const,
46
+ symbol: 'companyScrapeWorkflow',
47
+ description: 'Workflow definition bound to this OM resource descriptor.'
48
+ }
49
+ ]
50
+ }
51
+
52
+ const WORKFLOW_EVENT_EMISSION = {
53
+ eventKey: 'processed',
54
+ label: 'Processed',
55
+ payloadSchema: 'leadgen.company.processed',
56
+ lifecycle: 'active' as const
57
+ }
58
+
59
+ const AGENT_RESOURCE = {
60
+ id: 'command-center-assistant',
61
+ order: 20,
62
+ kind: 'agent' as const,
63
+ systemPath: 'sys.lead-gen',
64
+ ownerRoleId: 'role.sales-ops',
65
+ status: 'active' as const,
66
+ agentKind: 'platform' as const,
67
+ actsAsRoleId: 'role.sales-ops',
68
+ sessionCapable: true,
69
+ invocations: [{ kind: 'slash-command' as const, command: '/work handoff' }]
70
+ }
71
+
72
+ const INTEGRATION_RESOURCE = {
73
+ id: 'attio-crm',
74
+ order: 30,
75
+ kind: 'integration' as const,
76
+ systemPath: 'sys.lead-gen',
77
+ ownerRoleId: 'role.sales-ops',
78
+ status: 'active' as const,
79
+ provider: 'attio'
80
+ }
81
+
82
+ const SCRIPT_RESOURCE = {
83
+ id: 'leadgen-backfill-script',
84
+ order: 40,
85
+ kind: 'script' as const,
86
+ systemPath: 'sys.lead-gen',
87
+ ownerRoleId: 'role.sales-ops',
88
+ status: 'active' as const,
89
+ language: 'typescript' as const,
90
+ source: {
91
+ file: 'scripts/leadgen/backfill.ts'
92
+ }
93
+ }
94
+
95
+ function resolveWithResources(resources: Record<string, unknown>) {
96
+ return resolveOrganizationModel({
97
+ roles: { 'role.sales-ops': VALID_ROLE },
98
+ systems: { 'sys.lead-gen': VALID_SYSTEM },
99
+ resources: resources as Record<string, typeof WORKFLOW_RESOURCE>
100
+ })
101
+ }
102
+
103
+ describe('ResourceEntrySchema', () => {
104
+ it('accepts workflow, agent, integration, and script descriptors with required systemPath', () => {
105
+ expect(ResourceEntrySchema.safeParse(WORKFLOW_RESOURCE).success).toBe(true)
106
+ expect(ResourceEntrySchema.safeParse(AGENT_RESOURCE).success).toBe(true)
107
+ expect(ResourceEntrySchema.safeParse(INTEGRATION_RESOURCE).success).toBe(true)
108
+ expect(ResourceEntrySchema.safeParse(SCRIPT_RESOURCE).success).toBe(true)
109
+ })
110
+
111
+ it('rejects resources without a systemPath', () => {
112
+ const { systemPath: _systemPath, ...resourceWithoutSystem } = WORKFLOW_RESOURCE
113
+
114
+ expect(ResourceEntrySchema.safeParse(resourceWithoutSystem).success).toBe(false)
115
+ })
116
+
117
+ it('defaults codeRefs and accepts resource-level implementation breadcrumbs', () => {
118
+ const withCodeRefs = ResourceEntrySchema.safeParse(WORKFLOW_RESOURCE)
119
+ const withoutCodeRefs = ResourceEntrySchema.safeParse({
120
+ ...WORKFLOW_RESOURCE,
121
+ codeRefs: undefined
122
+ })
123
+
124
+ expect(withCodeRefs.success).toBe(true)
125
+ expect(withoutCodeRefs.success).toBe(true)
126
+
127
+ if (withCodeRefs.success) {
128
+ expect(withCodeRefs.data.codeRefs).toEqual(WORKFLOW_RESOURCE.codeRefs)
129
+ }
130
+ if (withoutCodeRefs.success) {
131
+ expect(withoutCodeRefs.data.codeRefs).toEqual([])
132
+ }
133
+ })
134
+
135
+ it('rejects codeRefs with an empty path', () => {
136
+ expect(
137
+ ResourceEntrySchema.safeParse({
138
+ ...WORKFLOW_RESOURCE,
139
+ codeRefs: [
140
+ {
141
+ path: ' ',
142
+ role: 'entrypoint'
143
+ }
144
+ ]
145
+ }).success
146
+ ).toBe(false)
147
+ })
148
+
149
+ it('rejects codeRefs with an invalid role', () => {
150
+ expect(
151
+ ResourceEntrySchema.safeParse({
152
+ ...WORKFLOW_RESOURCE,
153
+ codeRefs: [
154
+ {
155
+ path: 'operations/src/lead-gen/company-scrape/index.ts',
156
+ role: 'runtime'
157
+ }
158
+ ]
159
+ }).success
160
+ ).toBe(false)
161
+ })
162
+
163
+ it('rejects multi-system membership', () => {
164
+ expect(
165
+ ResourceEntrySchema.safeParse({
166
+ ...WORKFLOW_RESOURCE,
167
+ systemPath: ['sys.lead-gen', 'sys.crm']
168
+ }).success
169
+ ).toBe(false)
170
+ })
171
+
172
+ it('rejects an agent kind outside the code-side mirror enum', () => {
173
+ expect(
174
+ ResourceEntrySchema.safeParse({
175
+ ...AGENT_RESOURCE,
176
+ agentKind: 'runner'
177
+ }).success
178
+ ).toBe(false)
179
+ })
180
+
181
+ it('defaults agent invocations and accepts slash-command orchestration entries', () => {
182
+ const result = ResourceEntrySchema.safeParse({
183
+ ...AGENT_RESOURCE,
184
+ invocations: undefined
185
+ })
186
+
187
+ expect(result.success).toBe(true)
188
+ if (result.success) {
189
+ expect(result.data.kind).toBe('agent')
190
+ if (result.data.kind === 'agent') {
191
+ expect(result.data.invocations).toEqual([])
192
+ }
193
+ }
194
+
195
+ expect(ResourceEntrySchema.safeParse(AGENT_RESOURCE).success).toBe(true)
196
+ })
197
+
198
+ it('rejects malformed agent invocation entries', () => {
199
+ expect(
200
+ ResourceEntrySchema.safeParse({
201
+ ...AGENT_RESOURCE,
202
+ invocations: [{ kind: 'slash-command', command: 'work handoff' }]
203
+ }).success
204
+ ).toBe(false)
205
+ })
206
+
205
207
  it('accepts event emissions on workflow and agent resources only', () => {
206
- const workflowResult = ResourceEntrySchema.safeParse({
207
- ...WORKFLOW_RESOURCE,
208
- emits: [WORKFLOW_EVENT_EMISSION]
209
- })
210
- const agentResult = ResourceEntrySchema.safeParse({
211
- ...AGENT_RESOURCE,
212
- emits: [{ eventKey: 'approved', label: 'Approved' }]
213
- })
214
- const integrationResult = ResourceEntrySchema.safeParse({
215
- ...INTEGRATION_RESOURCE,
216
- emits: [{ eventKey: 'received', label: 'Received' }]
217
- })
218
-
219
- expect(workflowResult.success).toBe(true)
220
- expect(agentResult.success).toBe(true)
221
- expect(integrationResult.success).toBe(true)
222
- if (workflowResult.success && workflowResult.data.kind === 'workflow') {
223
- expect(workflowResult.data.emits).toEqual([WORKFLOW_EVENT_EMISSION])
224
- }
225
- if (agentResult.success && agentResult.data.kind === 'agent') {
226
- expect(agentResult.data.emits).toEqual([{ eventKey: 'approved', label: 'Approved' }])
227
- }
228
- if (integrationResult.success && integrationResult.data.kind === 'integration') {
229
- expect('emits' in integrationResult.data).toBe(false)
208
+ const workflowResult = ResourceEntrySchema.safeParse({
209
+ ...WORKFLOW_RESOURCE,
210
+ emits: [WORKFLOW_EVENT_EMISSION]
211
+ })
212
+ const agentResult = ResourceEntrySchema.safeParse({
213
+ ...AGENT_RESOURCE,
214
+ emits: [{ eventKey: 'approved', label: 'Approved' }]
215
+ })
216
+ const integrationResult = ResourceEntrySchema.safeParse({
217
+ ...INTEGRATION_RESOURCE,
218
+ emits: [{ eventKey: 'received', label: 'Received' }]
219
+ })
220
+
221
+ expect(workflowResult.success).toBe(true)
222
+ expect(agentResult.success).toBe(true)
223
+ expect(integrationResult.success).toBe(true)
224
+ if (workflowResult.success && workflowResult.data.kind === 'workflow') {
225
+ expect(workflowResult.data.emits).toEqual([WORKFLOW_EVENT_EMISSION])
226
+ }
227
+ if (agentResult.success && agentResult.data.kind === 'agent') {
228
+ expect(agentResult.data.emits).toEqual([{ eventKey: 'approved', label: 'Approved' }])
229
+ }
230
+ if (integrationResult.success && integrationResult.data.kind === 'integration') {
231
+ expect('emits' in integrationResult.data).toBe(false)
230
232
  }
231
233
  })
232
234
 
@@ -285,136 +287,281 @@ describe('ResourceEntrySchema', () => {
285
287
  })
286
288
 
287
289
  it('validates derived event id format', () => {
288
- expect(EventIdSchema.parse('crm.deal:won')).toBe('crm.deal:won')
289
- expect(EventIdSchema.parse('LGN-01-company-scrape:processed')).toBe('LGN-01-company-scrape:processed')
290
- expect(() => EventIdSchema.parse('crm.deal.won')).toThrow()
291
- })
292
- })
293
-
294
- describe('ResourcesDomainSchema', () => {
295
- it('defaults resources to an empty record when omitted', () => {
296
- const result = ResourcesDomainSchema.safeParse({})
297
-
298
- expect(result.success).toBe(true)
299
- if (result.success) {
300
- expect(result.data).toEqual(DEFAULT_ORGANIZATION_MODEL_RESOURCES)
301
- }
302
- })
303
-
304
- it.each(['workflow', 'agent', 'integration', 'script'] as const)('accepts kind "%s"', (kind) => {
305
- expect(ResourceKindSchema.safeParse(kind).success).toBe(true)
306
- })
307
- })
308
-
309
- describe('resolveOrganizationModel - resources domain integration', () => {
310
- it('accepts valid resources with system and role references', () => {
311
- const model = resolveWithResources({
312
- 'LGN-01-company-scrape': WORKFLOW_RESOURCE,
313
- 'command-center-assistant': AGENT_RESOURCE,
314
- 'attio-crm': INTEGRATION_RESOURCE,
315
- 'leadgen-backfill-script': SCRIPT_RESOURCE
316
- })
317
-
318
- expect(Object.keys(model.resources)).toHaveLength(4)
319
- })
320
-
321
- it('throws when a resource entry id does not match its map key', () => {
322
- expect(() =>
323
- resolveWithResources({
324
- 'LGN-01-company-scrape': WORKFLOW_RESOURCE,
325
- 'wrong-key': {
326
- ...WORKFLOW_RESOURCE,
327
- id: 'LGN-01-company-scrape'
328
- }
329
- })
330
- ).toThrow()
331
- })
332
-
333
- it('throws when systemPath references an unknown system', () => {
334
- expect(() =>
335
- resolveWithResources({
336
- 'LGN-01-company-scrape': {
337
- ...WORKFLOW_RESOURCE,
338
- systemPath: 'sys.missing'
339
- }
340
- })
341
- ).toThrow(/unknown system path \\"sys\.missing\\"/)
342
- })
343
-
344
- it('reports a dangling resource systemPath on the resource systemPath issue path', () => {
345
- let error: unknown
346
-
347
- try {
348
- resolveWithResources({
349
- 'LGN-01-company-scrape': {
350
- ...WORKFLOW_RESOURCE,
351
- systemPath: 'sys.missing'
352
- }
353
- })
354
- } catch (caught) {
355
- error = caught
356
- }
357
-
358
- expect(error).toBeInstanceOf(ZodError)
359
- if (!(error instanceof ZodError)) {
360
- throw new Error('Expected resolveOrganizationModel to throw a ZodError')
361
- }
362
-
363
- expect(error.issues).toEqual(
364
- expect.arrayContaining([
365
- expect.objectContaining({
366
- path: ['resources', 'LGN-01-company-scrape', 'systemPath']
367
- })
368
- ])
369
- )
370
- })
371
-
372
- it('throws when ownerRoleId references an unknown role', () => {
373
- expect(() =>
374
- resolveWithResources({
375
- 'LGN-01-company-scrape': {
376
- ...WORKFLOW_RESOURCE,
377
- ownerRoleId: 'role.missing'
378
- }
379
- })
380
- ).toThrow(/unknown ownerRoleId \\"role\.missing\\"/)
381
- })
382
-
383
- it('throws when agent actsAsRoleId references an unknown role', () => {
384
- expect(() =>
385
- resolveWithResources({
386
- 'command-center-assistant': {
387
- ...AGENT_RESOURCE,
388
- actsAsRoleId: 'role.missing'
389
- }
390
- })
391
- ).toThrow(/unknown actsAsRoleId \\"role\.missing\\"/)
392
- })
393
- })
394
-
395
- describe('descriptor helper contract', () => {
396
- it('preserves typed descriptor exports through defineResource and defineResources', () => {
397
- const workflow = defineResource(WORKFLOW_RESOURCE)
398
- const resources = defineResources({
399
- companyScrape: WORKFLOW_RESOURCE,
400
- commandCenterAssistant: AGENT_RESOURCE
401
- })
402
-
403
- expect(workflow.id).toBe('LGN-01-company-scrape')
404
- expect(resources.commandCenterAssistant.agentKind).toBe('platform')
405
- })
406
-
407
- it('derives runtime resourceId and type from the descriptor', () => {
408
- const bound = bindResourceDescriptor({
409
- resource: WORKFLOW_RESOURCE,
410
- name: 'Company Scrape',
411
- description: 'Scrapes company data for lead generation.',
412
- version: '1.0.0',
413
- status: 'prod'
414
- })
415
-
416
- expect(bound.resourceId).toBe('LGN-01-company-scrape')
417
- expect(bound.type).toBe('workflow')
418
- expect(bound.resource).toBe(WORKFLOW_RESOURCE)
419
- })
420
- })
290
+ expect(EventIdSchema.parse('crm.deal:won')).toBe('crm.deal:won')
291
+ expect(EventIdSchema.parse('LGN-01-company-scrape:processed')).toBe('LGN-01-company-scrape:processed')
292
+ expect(() => EventIdSchema.parse('crm.deal.won')).toThrow()
293
+ })
294
+ })
295
+
296
+ describe('ResourcesDomainSchema', () => {
297
+ it('defaults resources to an empty record when omitted', () => {
298
+ const result = ResourcesDomainSchema.safeParse({})
299
+
300
+ expect(result.success).toBe(true)
301
+ if (result.success) {
302
+ expect(result.data).toEqual(DEFAULT_ORGANIZATION_MODEL_RESOURCES)
303
+ }
304
+ })
305
+
306
+ it.each(['workflow', 'agent', 'integration', 'script'] as const)('accepts kind "%s"', (kind) => {
307
+ expect(ResourceKindSchema.safeParse(kind).success).toBe(true)
308
+ })
309
+ })
310
+
311
+ describe('resolveOrganizationModel - resources domain integration', () => {
312
+ it('accepts valid resources with system and role references', () => {
313
+ const model = resolveWithResources({
314
+ 'LGN-01-company-scrape': WORKFLOW_RESOURCE,
315
+ 'command-center-assistant': AGENT_RESOURCE,
316
+ 'attio-crm': INTEGRATION_RESOURCE,
317
+ 'leadgen-backfill-script': SCRIPT_RESOURCE
318
+ })
319
+
320
+ expect(Object.keys(model.resources)).toHaveLength(4)
321
+ })
322
+
323
+ it('throws when a resource entry id does not match its map key', () => {
324
+ expect(() =>
325
+ resolveWithResources({
326
+ 'LGN-01-company-scrape': WORKFLOW_RESOURCE,
327
+ 'wrong-key': {
328
+ ...WORKFLOW_RESOURCE,
329
+ id: 'LGN-01-company-scrape'
330
+ }
331
+ })
332
+ ).toThrow()
333
+ })
334
+
335
+ it('throws when systemPath references an unknown system', () => {
336
+ expect(() =>
337
+ resolveWithResources({
338
+ 'LGN-01-company-scrape': {
339
+ ...WORKFLOW_RESOURCE,
340
+ systemPath: 'sys.missing'
341
+ }
342
+ })
343
+ ).toThrow(/unknown system path \\"sys\.missing\\"/)
344
+ })
345
+
346
+ it('reports a dangling resource systemPath on the resource systemPath issue path', () => {
347
+ let error: unknown
348
+
349
+ try {
350
+ resolveWithResources({
351
+ 'LGN-01-company-scrape': {
352
+ ...WORKFLOW_RESOURCE,
353
+ systemPath: 'sys.missing'
354
+ }
355
+ })
356
+ } catch (caught) {
357
+ error = caught
358
+ }
359
+
360
+ expect(error).toBeInstanceOf(ZodError)
361
+ if (!(error instanceof ZodError)) {
362
+ throw new Error('Expected resolveOrganizationModel to throw a ZodError')
363
+ }
364
+
365
+ expect(error.issues).toEqual(
366
+ expect.arrayContaining([
367
+ expect.objectContaining({
368
+ path: ['resources', 'LGN-01-company-scrape', 'systemPath']
369
+ })
370
+ ])
371
+ )
372
+ })
373
+
374
+ it('throws when ownerRoleId references an unknown role', () => {
375
+ expect(() =>
376
+ resolveWithResources({
377
+ 'LGN-01-company-scrape': {
378
+ ...WORKFLOW_RESOURCE,
379
+ ownerRoleId: 'role.missing'
380
+ }
381
+ })
382
+ ).toThrow(/unknown ownerRoleId \\"role\.missing\\"/)
383
+ })
384
+
385
+ it('throws when agent actsAsRoleId references an unknown role', () => {
386
+ expect(() =>
387
+ resolveWithResources({
388
+ 'command-center-assistant': {
389
+ ...AGENT_RESOURCE,
390
+ actsAsRoleId: 'role.missing'
391
+ }
392
+ })
393
+ ).toThrow(/unknown actsAsRoleId \\"role\.missing\\"/)
394
+ })
395
+ })
396
+
397
+ describe('descriptor helper contract', () => {
398
+ it('preserves typed descriptor exports through defineResource and defineResources', () => {
399
+ const workflow = defineResource(WORKFLOW_RESOURCE)
400
+ const resources = defineResources({
401
+ companyScrape: WORKFLOW_RESOURCE,
402
+ commandCenterAssistant: AGENT_RESOURCE
403
+ })
404
+
405
+ expect(workflow.id).toBe('LGN-01-company-scrape')
406
+ expect(resources.commandCenterAssistant.agentKind).toBe('platform')
407
+ })
408
+
409
+ it('derives runtime resourceId and type from the descriptor', () => {
410
+ const bound = bindResourceDescriptor({
411
+ resource: WORKFLOW_RESOURCE,
412
+ name: 'Company Scrape',
413
+ description: 'Scrapes company data for lead generation.',
414
+ version: '1.0.0',
415
+ status: 'prod'
416
+ })
417
+
418
+ expect(bound.resourceId).toBe('LGN-01-company-scrape')
419
+ expect(bound.type).toBe('workflow')
420
+ expect(bound.resource).toBe(WORKFLOW_RESOURCE)
421
+ })
422
+ })
423
+
424
+ describe('ContractRefSchema — ref string shape', () => {
425
+ it('accepts valid package/subpath#ExportName refs', () => {
426
+ expect(ContractRefSchema.safeParse('@repo/elevasis-core/contracts/apollo-import#inputSchema').success).toBe(true)
427
+ expect(
428
+ ContractRefSchema.safeParse('@repo/elevasis-core/contracts/dtc-subscription-score#outputSchema').success
429
+ ).toBe(true)
430
+ expect(ContractRefSchema.safeParse('my-package/sub/path#MySchema').success).toBe(true)
431
+ expect(ContractRefSchema.safeParse('pkg#schema').success).toBe(true)
432
+ })
433
+
434
+ it('rejects refs without a #ExportName suffix', () => {
435
+ expect(ContractRefSchema.safeParse('@repo/elevasis-core/contracts/apollo-import').success).toBe(false)
436
+ expect(ContractRefSchema.safeParse('pkg/sub').success).toBe(false)
437
+ })
438
+
439
+ it('rejects refs with an empty export name after #', () => {
440
+ expect(ContractRefSchema.safeParse('@repo/elevasis-core/contracts/apollo-import#').success).toBe(false)
441
+ })
442
+
443
+ it('rejects empty strings', () => {
444
+ expect(ContractRefSchema.safeParse('').success).toBe(false)
445
+ })
446
+ })
447
+
448
+ describe('parseContractRef — browser-safe parser', () => {
449
+ it('parses a valid ref into moduleSpecifier and exportName', () => {
450
+ const result = parseContractRef('@repo/elevasis-core/contracts/apollo-import#inputSchema')
451
+ expect(result.moduleSpecifier).toBe('@repo/elevasis-core/contracts/apollo-import')
452
+ expect(result.exportName).toBe('inputSchema')
453
+ })
454
+
455
+ it('uses lastIndexOf so a # in the module specifier (unusual but valid) is handled correctly', () => {
456
+ const result = parseContractRef('pkg/sub#Export#actualExport')
457
+ expect(result.moduleSpecifier).toBe('pkg/sub#Export')
458
+ expect(result.exportName).toBe('actualExport')
459
+ })
460
+
461
+ it('throws on a ref without #', () => {
462
+ expect(() => parseContractRef('pkg/no-hash')).toThrow(/missing the required/)
463
+ })
464
+
465
+ it('throws on a ref with empty export name', () => {
466
+ expect(() => parseContractRef('pkg/sub#')).toThrow(/empty export name/)
467
+ })
468
+ })
469
+
470
+ describe('ResourceOntologyBindingSchema — contract field', () => {
471
+ it('accepts a binding without a contract field (backward compat)', () => {
472
+ expect(
473
+ ResourceOntologyBindingSchema.safeParse({
474
+ actions: ['sys.lead-gen:action/company.scrape']
475
+ }).success
476
+ ).toBe(true)
477
+ })
478
+
479
+ it('accepts a binding with a valid contract.input ref', () => {
480
+ expect(
481
+ ResourceOntologyBindingSchema.safeParse({
482
+ contract: {
483
+ input: '@repo/elevasis-core/contracts/apollo-import#inputSchema'
484
+ }
485
+ }).success
486
+ ).toBe(true)
487
+ })
488
+
489
+ it('accepts a binding with both contract.input and contract.output refs', () => {
490
+ expect(
491
+ ResourceOntologyBindingSchema.safeParse({
492
+ contract: {
493
+ input: '@repo/elevasis-core/contracts/dtc-subscription-score#inputSchema',
494
+ output: '@repo/elevasis-core/contracts/dtc-subscription-score#outputSchema'
495
+ }
496
+ }).success
497
+ ).toBe(true)
498
+ })
499
+
500
+ it('accepts a binding with an empty contract object (both sides optional)', () => {
501
+ expect(
502
+ ResourceOntologyBindingSchema.safeParse({
503
+ contract: {}
504
+ }).success
505
+ ).toBe(true)
506
+ })
507
+
508
+ it('rejects a malformed contract.input ref (missing #ExportName)', () => {
509
+ expect(
510
+ ResourceOntologyBindingSchema.safeParse({
511
+ contract: {
512
+ input: '@repo/elevasis-core/contracts/apollo-import'
513
+ }
514
+ }).success
515
+ ).toBe(false)
516
+ })
517
+
518
+ it('rejects a malformed contract.output ref (missing #ExportName)', () => {
519
+ expect(
520
+ ResourceOntologyBindingSchema.safeParse({
521
+ contract: {
522
+ output: 'not-a-valid-ref'
523
+ }
524
+ }).success
525
+ ).toBe(false)
526
+ })
527
+ })
528
+
529
+ describe('resolveOrganizationModel — contract ref Tier-1 shape validation', () => {
530
+ it('accepts a resource with a valid contract binding', () => {
531
+ const model = resolveWithResources({
532
+ 'LGN-01-company-scrape': {
533
+ ...WORKFLOW_RESOURCE,
534
+ ontology: {
535
+ contract: {
536
+ input: '@repo/elevasis-core/contracts/apollo-import#inputSchema'
537
+ }
538
+ }
539
+ }
540
+ })
541
+ expect(model.resources['LGN-01-company-scrape']?.ontology?.contract?.input).toBe(
542
+ '@repo/elevasis-core/contracts/apollo-import#inputSchema'
543
+ )
544
+ })
545
+
546
+ it('rejects a resource with a malformed contract.input ref', () => {
547
+ expect(() =>
548
+ resolveWithResources({
549
+ 'LGN-01-company-scrape': {
550
+ ...WORKFLOW_RESOURCE,
551
+ ontology: {
552
+ contract: {
553
+ input: 'bad-ref-no-hash'
554
+ }
555
+ }
556
+ }
557
+ })
558
+ ).toThrow()
559
+ })
560
+
561
+ it('leaves resources without contract binding unchanged (additive + optional)', () => {
562
+ const model = resolveWithResources({
563
+ 'LGN-01-company-scrape': WORKFLOW_RESOURCE
564
+ })
565
+ expect(model.resources['LGN-01-company-scrape']?.ontology).toBeUndefined()
566
+ })
567
+ })