@elevasis/core 0.22.0 → 0.23.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.
- package/dist/index.d.ts +2330 -2391
- package/dist/index.js +2322 -1147
- package/dist/knowledge/index.d.ts +702 -1136
- package/dist/knowledge/index.js +9 -9
- package/dist/organization-model/index.d.ts +2330 -2391
- package/dist/organization-model/index.js +2322 -1147
- package/dist/test-utils/index.d.ts +703 -1106
- package/dist/test-utils/index.js +1735 -1089
- package/package.json +1 -1
- package/src/__tests__/template-core-compatibility.test.ts +11 -79
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +360 -98
- package/src/business/acquisition/api-schemas.test.ts +2 -2
- package/src/business/acquisition/api-schemas.ts +7 -9
- package/src/business/acquisition/build-templates.test.ts +4 -4
- package/src/business/acquisition/build-templates.ts +72 -30
- package/src/business/acquisition/crm-state-actions.test.ts +13 -11
- package/src/business/acquisition/types.ts +7 -3
- package/src/execution/engine/agent/core/types.ts +1 -1
- package/src/execution/engine/workflow/types.ts +2 -2
- package/src/knowledge/README.md +8 -7
- package/src/knowledge/__tests__/queries.test.ts +74 -73
- package/src/knowledge/format.ts +10 -9
- package/src/knowledge/index.ts +1 -1
- package/src/knowledge/published.ts +1 -1
- package/src/knowledge/queries.ts +26 -25
- package/src/organization-model/README.md +66 -26
- package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
- package/src/organization-model/__tests__/defaults.test.ts +72 -98
- package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
- package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
- package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
- package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
- package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
- package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
- package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
- package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
- package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
- package/src/organization-model/__tests__/domains/resources.test.ts +159 -37
- package/src/organization-model/__tests__/domains/roles.test.ts +147 -86
- package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
- package/src/organization-model/__tests__/domains/systems.test.ts +67 -51
- package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
- package/src/organization-model/__tests__/foundation.test.ts +74 -102
- package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
- package/src/organization-model/__tests__/graph.test.ts +899 -71
- package/src/organization-model/__tests__/knowledge.test.ts +173 -52
- package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
- package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
- package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
- package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
- package/src/organization-model/__tests__/resolve.test.ts +174 -23
- package/src/organization-model/__tests__/schema.test.ts +291 -114
- package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
- package/src/organization-model/catalogs/lead-gen.ts +144 -0
- package/src/organization-model/content-kinds/config.ts +36 -0
- package/src/organization-model/content-kinds/index.ts +74 -0
- package/src/organization-model/content-kinds/pipeline.ts +68 -0
- package/src/organization-model/content-kinds/registry.ts +44 -0
- package/src/organization-model/content-kinds/status.ts +71 -0
- package/src/organization-model/content-kinds/template.ts +83 -0
- package/src/organization-model/content-kinds/types.ts +117 -0
- package/src/organization-model/contracts.ts +13 -3
- package/src/organization-model/defaults.ts +488 -96
- package/src/organization-model/domains/actions.ts +239 -0
- package/src/organization-model/domains/customers.ts +78 -75
- package/src/organization-model/domains/entities.ts +144 -0
- package/src/organization-model/domains/goals.ts +83 -80
- package/src/organization-model/domains/knowledge.ts +74 -16
- package/src/organization-model/domains/navigation.ts +107 -384
- package/src/organization-model/domains/offerings.ts +71 -66
- package/src/organization-model/domains/policies.ts +102 -0
- package/src/organization-model/domains/projects.ts +14 -48
- package/src/organization-model/domains/prospecting.ts +62 -181
- package/src/organization-model/domains/resources.ts +81 -24
- package/src/organization-model/domains/roles.ts +13 -10
- package/src/organization-model/domains/sales.ts +10 -219
- package/src/organization-model/domains/shared.ts +57 -57
- package/src/organization-model/domains/statuses.ts +339 -130
- package/src/organization-model/domains/systems.ts +186 -29
- package/src/organization-model/foundation.ts +54 -67
- package/src/organization-model/graph/build.ts +682 -54
- package/src/organization-model/graph/link.ts +1 -1
- package/src/organization-model/graph/schema.ts +24 -9
- package/src/organization-model/graph/types.ts +20 -7
- package/src/organization-model/helpers.ts +231 -26
- package/src/organization-model/index.ts +116 -5
- package/src/organization-model/migration-helpers.ts +249 -0
- package/src/organization-model/organization-graph.mdx +16 -15
- package/src/organization-model/organization-model.mdx +89 -41
- package/src/organization-model/published.ts +120 -18
- package/src/organization-model/resolve.ts +117 -54
- package/src/organization-model/schema.ts +561 -140
- package/src/organization-model/surface-projection.ts +116 -122
- package/src/organization-model/types.ts +102 -21
- package/src/platform/constants/versions.ts +1 -1
- package/src/platform/registry/__tests__/command-view.test.ts +6 -8
- package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
- package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
- package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
- package/src/platform/registry/__tests__/resource-registry.test.ts +9 -7
- package/src/platform/registry/__tests__/validation.test.ts +15 -11
- package/src/platform/registry/resource-registry.ts +20 -8
- package/src/platform/registry/serialization.ts +7 -7
- package/src/platform/registry/types.ts +3 -3
- package/src/platform/registry/validation.ts +17 -15
- package/src/reference/_generated/contracts.md +362 -99
- package/src/reference/glossary.md +18 -18
- package/src/supabase/database.types.ts +60 -0
- package/src/test-utils/test-utils.test.ts +1 -6
- package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
- package/src/organization-model/domains/features.ts +0 -31
- package/src/organization-model/domains/operations.ts +0 -85
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { ZodError } from 'zod'
|
|
2
3
|
import { bindResourceDescriptor } from '../../../platform/registry/types'
|
|
3
4
|
import {
|
|
4
5
|
DEFAULT_ORGANIZATION_MODEL_RESOURCES,
|
|
6
|
+
EventIdSchema,
|
|
5
7
|
ResourceEntrySchema,
|
|
6
8
|
ResourceKindSchema,
|
|
7
9
|
ResourcesDomainSchema,
|
|
@@ -12,6 +14,7 @@ import { resolveOrganizationModel } from '../../resolve'
|
|
|
12
14
|
|
|
13
15
|
const VALID_SYSTEM = {
|
|
14
16
|
id: 'sys.lead-gen',
|
|
17
|
+
order: 10,
|
|
15
18
|
title: 'Lead Generation Pipeline',
|
|
16
19
|
description: 'Coordinates prospecting, enrichment, qualification, and outreach preparation.',
|
|
17
20
|
kind: 'operational' as const,
|
|
@@ -20,55 +23,81 @@ const VALID_SYSTEM = {
|
|
|
20
23
|
|
|
21
24
|
const VALID_ROLE = {
|
|
22
25
|
id: 'role.sales-ops',
|
|
26
|
+
order: 10,
|
|
23
27
|
title: 'Sales Ops'
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
const WORKFLOW_RESOURCE = {
|
|
27
31
|
id: 'LGN-01-company-scrape',
|
|
32
|
+
order: 10,
|
|
28
33
|
kind: 'workflow' as const,
|
|
29
|
-
|
|
34
|
+
systemPath: 'sys.lead-gen',
|
|
30
35
|
ownerRoleId: 'role.sales-ops',
|
|
31
36
|
status: 'active' as const,
|
|
32
|
-
|
|
37
|
+
actionKey: 'lead-gen.company.scrape'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const WORKFLOW_EVENT_EMISSION = {
|
|
41
|
+
eventKey: 'processed',
|
|
42
|
+
label: 'Processed',
|
|
43
|
+
payloadSchema: 'leadgen.company.processed',
|
|
44
|
+
lifecycle: 'active' as const
|
|
33
45
|
}
|
|
34
46
|
|
|
35
47
|
const AGENT_RESOURCE = {
|
|
36
48
|
id: 'command-center-assistant',
|
|
49
|
+
order: 20,
|
|
37
50
|
kind: 'agent' as const,
|
|
38
|
-
|
|
51
|
+
systemPath: 'sys.lead-gen',
|
|
39
52
|
ownerRoleId: 'role.sales-ops',
|
|
40
53
|
status: 'active' as const,
|
|
41
|
-
agentKind: '
|
|
54
|
+
agentKind: 'platform' as const,
|
|
42
55
|
actsAsRoleId: 'role.sales-ops',
|
|
43
|
-
sessionCapable: true
|
|
56
|
+
sessionCapable: true,
|
|
57
|
+
invocations: [{ kind: 'slash-command' as const, command: '/work handoff' }]
|
|
44
58
|
}
|
|
45
59
|
|
|
46
60
|
const INTEGRATION_RESOURCE = {
|
|
47
61
|
id: 'attio-crm',
|
|
62
|
+
order: 30,
|
|
48
63
|
kind: 'integration' as const,
|
|
49
|
-
|
|
64
|
+
systemPath: 'sys.lead-gen',
|
|
50
65
|
ownerRoleId: 'role.sales-ops',
|
|
51
66
|
status: 'active' as const,
|
|
52
67
|
provider: 'attio'
|
|
53
68
|
}
|
|
54
69
|
|
|
55
|
-
|
|
70
|
+
const SCRIPT_RESOURCE = {
|
|
71
|
+
id: 'leadgen-backfill-script',
|
|
72
|
+
order: 40,
|
|
73
|
+
kind: 'script' as const,
|
|
74
|
+
systemPath: 'sys.lead-gen',
|
|
75
|
+
ownerRoleId: 'role.sales-ops',
|
|
76
|
+
status: 'active' as const,
|
|
77
|
+
language: 'typescript' as const,
|
|
78
|
+
source: {
|
|
79
|
+
file: 'scripts/leadgen/backfill.ts'
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function resolveWithResources(resources: Record<string, unknown>) {
|
|
56
84
|
return resolveOrganizationModel({
|
|
57
|
-
roles: {
|
|
58
|
-
systems: {
|
|
59
|
-
resources:
|
|
85
|
+
roles: { 'role.sales-ops': VALID_ROLE },
|
|
86
|
+
systems: { 'sys.lead-gen': VALID_SYSTEM },
|
|
87
|
+
resources: resources as Record<string, typeof WORKFLOW_RESOURCE>
|
|
60
88
|
})
|
|
61
89
|
}
|
|
62
90
|
|
|
63
91
|
describe('ResourceEntrySchema', () => {
|
|
64
|
-
it('accepts workflow, agent, and
|
|
92
|
+
it('accepts workflow, agent, integration, and script descriptors with required systemPath', () => {
|
|
65
93
|
expect(ResourceEntrySchema.safeParse(WORKFLOW_RESOURCE).success).toBe(true)
|
|
66
94
|
expect(ResourceEntrySchema.safeParse(AGENT_RESOURCE).success).toBe(true)
|
|
67
95
|
expect(ResourceEntrySchema.safeParse(INTEGRATION_RESOURCE).success).toBe(true)
|
|
96
|
+
expect(ResourceEntrySchema.safeParse(SCRIPT_RESOURCE).success).toBe(true)
|
|
68
97
|
})
|
|
69
98
|
|
|
70
|
-
it('rejects resources without a
|
|
71
|
-
const {
|
|
99
|
+
it('rejects resources without a systemPath', () => {
|
|
100
|
+
const { systemPath: _systemPath, ...resourceWithoutSystem } = WORKFLOW_RESOURCE
|
|
72
101
|
|
|
73
102
|
expect(ResourceEntrySchema.safeParse(resourceWithoutSystem).success).toBe(false)
|
|
74
103
|
})
|
|
@@ -77,7 +106,7 @@ describe('ResourceEntrySchema', () => {
|
|
|
77
106
|
expect(
|
|
78
107
|
ResourceEntrySchema.safeParse({
|
|
79
108
|
...WORKFLOW_RESOURCE,
|
|
80
|
-
|
|
109
|
+
systemPath: ['sys.lead-gen', 'sys.crm']
|
|
81
110
|
}).success
|
|
82
111
|
).toBe(false)
|
|
83
112
|
})
|
|
@@ -90,10 +119,70 @@ describe('ResourceEntrySchema', () => {
|
|
|
90
119
|
}).success
|
|
91
120
|
).toBe(false)
|
|
92
121
|
})
|
|
122
|
+
|
|
123
|
+
it('defaults agent invocations and accepts slash-command orchestration entries', () => {
|
|
124
|
+
const result = ResourceEntrySchema.safeParse({
|
|
125
|
+
...AGENT_RESOURCE,
|
|
126
|
+
invocations: undefined
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
expect(result.success).toBe(true)
|
|
130
|
+
if (result.success) {
|
|
131
|
+
expect(result.data.kind).toBe('agent')
|
|
132
|
+
if (result.data.kind === 'agent') {
|
|
133
|
+
expect(result.data.invocations).toEqual([])
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
expect(ResourceEntrySchema.safeParse(AGENT_RESOURCE).success).toBe(true)
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
it('rejects malformed agent invocation entries', () => {
|
|
141
|
+
expect(
|
|
142
|
+
ResourceEntrySchema.safeParse({
|
|
143
|
+
...AGENT_RESOURCE,
|
|
144
|
+
invocations: [{ kind: 'slash-command', command: 'work handoff' }]
|
|
145
|
+
}).success
|
|
146
|
+
).toBe(false)
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('accepts event emissions on workflow and agent resources only', () => {
|
|
150
|
+
const workflowResult = ResourceEntrySchema.safeParse({
|
|
151
|
+
...WORKFLOW_RESOURCE,
|
|
152
|
+
emits: [WORKFLOW_EVENT_EMISSION]
|
|
153
|
+
})
|
|
154
|
+
const agentResult = ResourceEntrySchema.safeParse({
|
|
155
|
+
...AGENT_RESOURCE,
|
|
156
|
+
emits: [{ eventKey: 'approved', label: 'Approved' }]
|
|
157
|
+
})
|
|
158
|
+
const integrationResult = ResourceEntrySchema.safeParse({
|
|
159
|
+
...INTEGRATION_RESOURCE,
|
|
160
|
+
emits: [{ eventKey: 'received', label: 'Received' }]
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
expect(workflowResult.success).toBe(true)
|
|
164
|
+
expect(agentResult.success).toBe(true)
|
|
165
|
+
expect(integrationResult.success).toBe(true)
|
|
166
|
+
if (workflowResult.success && workflowResult.data.kind === 'workflow') {
|
|
167
|
+
expect(workflowResult.data.emits).toEqual([WORKFLOW_EVENT_EMISSION])
|
|
168
|
+
}
|
|
169
|
+
if (agentResult.success && agentResult.data.kind === 'agent') {
|
|
170
|
+
expect(agentResult.data.emits).toEqual([{ eventKey: 'approved', label: 'Approved' }])
|
|
171
|
+
}
|
|
172
|
+
if (integrationResult.success && integrationResult.data.kind === 'integration') {
|
|
173
|
+
expect('emits' in integrationResult.data).toBe(false)
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('validates derived event id format', () => {
|
|
178
|
+
expect(EventIdSchema.parse('crm.deal:won')).toBe('crm.deal:won')
|
|
179
|
+
expect(EventIdSchema.parse('LGN-01-company-scrape:processed')).toBe('LGN-01-company-scrape:processed')
|
|
180
|
+
expect(() => EventIdSchema.parse('crm.deal.won')).toThrow()
|
|
181
|
+
})
|
|
93
182
|
})
|
|
94
183
|
|
|
95
184
|
describe('ResourcesDomainSchema', () => {
|
|
96
|
-
it('defaults resources to an empty
|
|
185
|
+
it('defaults resources to an empty record when omitted', () => {
|
|
97
186
|
const result = ResourcesDomainSchema.safeParse({})
|
|
98
187
|
|
|
99
188
|
expect(result.success).toBe(true)
|
|
@@ -102,60 +191,93 @@ describe('ResourcesDomainSchema', () => {
|
|
|
102
191
|
}
|
|
103
192
|
})
|
|
104
193
|
|
|
105
|
-
it.each(['workflow', 'agent', 'integration'] as const)('accepts kind "%s"', (kind) => {
|
|
194
|
+
it.each(['workflow', 'agent', 'integration', 'script'] as const)('accepts kind "%s"', (kind) => {
|
|
106
195
|
expect(ResourceKindSchema.safeParse(kind).success).toBe(true)
|
|
107
196
|
})
|
|
108
197
|
})
|
|
109
198
|
|
|
110
199
|
describe('resolveOrganizationModel - resources domain integration', () => {
|
|
111
200
|
it('accepts valid resources with system and role references', () => {
|
|
112
|
-
const model = resolveWithResources(
|
|
201
|
+
const model = resolveWithResources({
|
|
202
|
+
'LGN-01-company-scrape': WORKFLOW_RESOURCE,
|
|
203
|
+
'command-center-assistant': AGENT_RESOURCE,
|
|
204
|
+
'attio-crm': INTEGRATION_RESOURCE,
|
|
205
|
+
'leadgen-backfill-script': SCRIPT_RESOURCE
|
|
206
|
+
})
|
|
113
207
|
|
|
114
|
-
expect(model.resources
|
|
208
|
+
expect(Object.keys(model.resources)).toHaveLength(4)
|
|
115
209
|
})
|
|
116
210
|
|
|
117
|
-
it('throws when resource
|
|
211
|
+
it('throws when a resource entry id does not match its map key', () => {
|
|
118
212
|
expect(() =>
|
|
119
|
-
resolveWithResources(
|
|
120
|
-
WORKFLOW_RESOURCE,
|
|
121
|
-
{
|
|
213
|
+
resolveWithResources({
|
|
214
|
+
'LGN-01-company-scrape': WORKFLOW_RESOURCE,
|
|
215
|
+
'wrong-key': {
|
|
122
216
|
...WORKFLOW_RESOURCE,
|
|
123
|
-
|
|
217
|
+
id: 'LGN-01-company-scrape'
|
|
124
218
|
}
|
|
125
|
-
|
|
126
|
-
).toThrow(
|
|
219
|
+
})
|
|
220
|
+
).toThrow()
|
|
127
221
|
})
|
|
128
222
|
|
|
129
|
-
it('throws when
|
|
223
|
+
it('throws when systemPath references an unknown system', () => {
|
|
130
224
|
expect(() =>
|
|
131
|
-
resolveWithResources(
|
|
132
|
-
{
|
|
225
|
+
resolveWithResources({
|
|
226
|
+
'LGN-01-company-scrape': {
|
|
133
227
|
...WORKFLOW_RESOURCE,
|
|
134
|
-
|
|
228
|
+
systemPath: 'sys.missing'
|
|
135
229
|
}
|
|
230
|
+
})
|
|
231
|
+
).toThrow(/unknown system path \\"sys\.missing\\"/)
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
it('reports a dangling resource systemPath on the resource systemPath issue path', () => {
|
|
235
|
+
let error: unknown
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
resolveWithResources({
|
|
239
|
+
'LGN-01-company-scrape': {
|
|
240
|
+
...WORKFLOW_RESOURCE,
|
|
241
|
+
systemPath: 'sys.missing'
|
|
242
|
+
}
|
|
243
|
+
})
|
|
244
|
+
} catch (caught) {
|
|
245
|
+
error = caught
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
expect(error).toBeInstanceOf(ZodError)
|
|
249
|
+
if (!(error instanceof ZodError)) {
|
|
250
|
+
throw new Error('Expected resolveOrganizationModel to throw a ZodError')
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
expect(error.issues).toEqual(
|
|
254
|
+
expect.arrayContaining([
|
|
255
|
+
expect.objectContaining({
|
|
256
|
+
path: ['resources', 'LGN-01-company-scrape', 'systemPath']
|
|
257
|
+
})
|
|
136
258
|
])
|
|
137
|
-
)
|
|
259
|
+
)
|
|
138
260
|
})
|
|
139
261
|
|
|
140
262
|
it('throws when ownerRoleId references an unknown role', () => {
|
|
141
263
|
expect(() =>
|
|
142
|
-
resolveWithResources(
|
|
143
|
-
{
|
|
264
|
+
resolveWithResources({
|
|
265
|
+
'LGN-01-company-scrape': {
|
|
144
266
|
...WORKFLOW_RESOURCE,
|
|
145
267
|
ownerRoleId: 'role.missing'
|
|
146
268
|
}
|
|
147
|
-
|
|
269
|
+
})
|
|
148
270
|
).toThrow(/unknown ownerRoleId \\"role\.missing\\"/)
|
|
149
271
|
})
|
|
150
272
|
|
|
151
273
|
it('throws when agent actsAsRoleId references an unknown role', () => {
|
|
152
274
|
expect(() =>
|
|
153
|
-
resolveWithResources(
|
|
154
|
-
{
|
|
275
|
+
resolveWithResources({
|
|
276
|
+
'command-center-assistant': {
|
|
155
277
|
...AGENT_RESOURCE,
|
|
156
278
|
actsAsRoleId: 'role.missing'
|
|
157
279
|
}
|
|
158
|
-
|
|
280
|
+
})
|
|
159
281
|
).toThrow(/unknown actsAsRoleId \\"role\.missing\\"/)
|
|
160
282
|
})
|
|
161
283
|
})
|
|
@@ -169,7 +291,7 @@ describe('descriptor helper contract', () => {
|
|
|
169
291
|
})
|
|
170
292
|
|
|
171
293
|
expect(workflow.id).toBe('LGN-01-company-scrape')
|
|
172
|
-
expect(resources.commandCenterAssistant.agentKind).toBe('
|
|
294
|
+
expect(resources.commandCenterAssistant.agentKind).toBe('platform')
|
|
173
295
|
})
|
|
174
296
|
|
|
175
297
|
it('derives runtime resourceId and type from the descriptor', () => {
|