@elevasis/core 0.27.0 → 0.29.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 +146 -89
- package/dist/index.js +116 -46
- package/dist/knowledge/index.d.ts +21 -21
- package/dist/organization-model/index.d.ts +146 -89
- package/dist/organization-model/index.js +116 -46
- package/dist/test-utils/index.d.ts +20 -17
- package/dist/test-utils/index.js +22 -20
- package/package.json +1 -1
- package/src/business/acquisition/api-schemas.test.ts +59 -8
- package/src/business/acquisition/api-schemas.ts +10 -5
- package/src/business/acquisition/build-templates.test.ts +187 -240
- package/src/business/acquisition/build-templates.ts +87 -98
- package/src/business/acquisition/types.ts +390 -389
- package/src/execution/engine/index.ts +6 -4
- package/src/execution/engine/tools/lead-service-types.ts +63 -34
- package/src/execution/engine/tools/platform/acquisition/types.ts +7 -8
- package/src/execution/engine/tools/registry.ts +6 -4
- package/src/execution/engine/tools/tool-maps.ts +23 -1
- package/src/organization-model/__tests__/define-domain-record.test.ts +289 -0
- package/src/organization-model/__tests__/om-spine-doc-contract.test.ts +56 -0
- package/src/organization-model/domains/actions.ts +13 -0
- package/src/organization-model/domains/customers.ts +95 -78
- package/src/organization-model/domains/entities.ts +157 -144
- package/src/organization-model/domains/goals.ts +100 -83
- package/src/organization-model/domains/knowledge.ts +106 -93
- package/src/organization-model/domains/offerings.ts +88 -71
- package/src/organization-model/domains/policies.ts +115 -102
- package/src/organization-model/domains/prospecting.ts +2 -327
- package/src/organization-model/domains/roles.ts +109 -96
- package/src/organization-model/domains/statuses.ts +351 -339
- package/src/organization-model/domains/systems.ts +176 -164
- package/src/organization-model/helpers.ts +331 -306
- package/src/organization-model/index.ts +42 -0
- package/src/organization-model/migration-helpers.ts +16 -12
- package/src/organization-model/published.ts +27 -2
- package/src/platform/constants/versions.ts +1 -1
- package/src/reference/_generated/contracts.md +376 -352
- package/src/supabase/database.types.ts +3 -0
|
@@ -1,78 +1,95 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
order:
|
|
35
|
-
|
|
36
|
-
name
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
*
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
*
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { defineDomainRecord } from '../helpers'
|
|
3
|
+
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Firmographics — optional demographic/firmographic filters that describe the
|
|
6
|
+
// target customer segment's organizational profile. All fields are optional so
|
|
7
|
+
// a segment can declare only the axes relevant to targeting.
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
export const FirmographicsSchema = z.object({
|
|
11
|
+
/** Industry vertical (e.g. "Marketing Agency", "Legal", "Real Estate"). */
|
|
12
|
+
industry: z.string().trim().max(200).optional(),
|
|
13
|
+
/**
|
|
14
|
+
* Company headcount band (e.g. "1–10", "11–50", "51–200", "200+").
|
|
15
|
+
* Free-form string to accommodate any band notation.
|
|
16
|
+
*/
|
|
17
|
+
companySize: z.string().trim().max(100).optional(),
|
|
18
|
+
/**
|
|
19
|
+
* Primary geographic region the segment operates in or is targeted from
|
|
20
|
+
* (e.g. "North America", "Europe", "Global").
|
|
21
|
+
*/
|
|
22
|
+
region: z.string().trim().max(200).optional()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Customer segment schema — one entry per distinct buyer archetype.
|
|
27
|
+
// Modeled after Value Proposition Canvas (BMC / VPC) and Business Model Canvas
|
|
28
|
+
// customer-segment language. Fields use plain English throughout.
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
export const CustomerSegmentSchema = z.object({
|
|
32
|
+
/** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
|
|
33
|
+
id: z.string().trim().min(1).max(100),
|
|
34
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
35
|
+
order: z.number(),
|
|
36
|
+
/** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
|
|
37
|
+
name: z.string().trim().max(200).default(''),
|
|
38
|
+
/** One or two sentences describing who this segment is. */
|
|
39
|
+
description: z.string().trim().max(2000).default(''),
|
|
40
|
+
/**
|
|
41
|
+
* The primary job(s) this segment is trying to get done — the goal they hire
|
|
42
|
+
* a product/service to accomplish. Plain-language narrative or bullet list.
|
|
43
|
+
*/
|
|
44
|
+
jobsToBeDone: z.string().trim().max(2000).default(''),
|
|
45
|
+
/**
|
|
46
|
+
* Pains — frustrations, obstacles, and risks the segment experiences
|
|
47
|
+
* when trying to accomplish their jobs-to-be-done.
|
|
48
|
+
*/
|
|
49
|
+
pains: z.array(z.string().trim().max(500)).default([]),
|
|
50
|
+
/**
|
|
51
|
+
* Gains — outcomes and benefits the segment desires; positive motivators
|
|
52
|
+
* beyond merely resolving pains.
|
|
53
|
+
*/
|
|
54
|
+
gains: z.array(z.string().trim().max(500)).default([]),
|
|
55
|
+
/** Firmographic profile for targeting and filtering. */
|
|
56
|
+
firmographics: FirmographicsSchema.default({}),
|
|
57
|
+
/**
|
|
58
|
+
* Value proposition — one or two sentences stating why this organization's
|
|
59
|
+
* offering is uniquely suited for this segment's needs.
|
|
60
|
+
*/
|
|
61
|
+
valueProp: z.string().trim().max(2000).default('')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Customers domain schema — id-keyed map of customer segments.
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
export const CustomersDomainSchema = z
|
|
69
|
+
.record(z.string(), CustomerSegmentSchema)
|
|
70
|
+
.refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
71
|
+
message: 'Each segment entry id must match its map key'
|
|
72
|
+
})
|
|
73
|
+
.default({})
|
|
74
|
+
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
// Seed — empty by default; adapters populate with real segment definitions.
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
export const DEFAULT_ORGANIZATION_MODEL_CUSTOMERS: z.infer<typeof CustomersDomainSchema> = {}
|
|
80
|
+
|
|
81
|
+
/** Validate and return a single customer segment entry. */
|
|
82
|
+
export function defineCustomer(entry: z.input<typeof CustomerSegmentSchema>): z.infer<typeof CustomerSegmentSchema> {
|
|
83
|
+
return CustomerSegmentSchema.parse(entry)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Validate and return an id-keyed map of customer segment entries. */
|
|
87
|
+
export function defineCustomers(
|
|
88
|
+
entries: readonly z.input<typeof CustomerSegmentSchema>[]
|
|
89
|
+
): Record<string, z.infer<typeof CustomerSegmentSchema>> {
|
|
90
|
+
return defineDomainRecord(CustomerSegmentSchema, entries)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type CustomerSegment = z.infer<typeof CustomerSegmentSchema>
|
|
94
|
+
export type CustomersDomain = z.infer<typeof CustomersDomainSchema>
|
|
95
|
+
export type Firmographics = z.infer<typeof FirmographicsSchema>
|
|
@@ -1,144 +1,157 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
import { DescriptionSchema, LabelSchema, ModelIdSchema } from './shared'
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
order:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{ toEntity: 'leadgen.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
{ toEntity: 'leadgen.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
{ toEntity: 'leadgen.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
{ toEntity: 'delivery.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
{ toEntity: 'delivery.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
{ toEntity: 'delivery.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
export
|
|
143
|
-
|
|
144
|
-
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { DescriptionSchema, LabelSchema, ModelIdSchema } from './shared'
|
|
3
|
+
import { defineDomainRecord } from '../helpers'
|
|
4
|
+
|
|
5
|
+
export const EntityIdSchema = ModelIdSchema
|
|
6
|
+
|
|
7
|
+
export const EntityLinkKindSchema = z
|
|
8
|
+
.enum(['belongs-to', 'has-many', 'has-one', 'many-to-many'])
|
|
9
|
+
.meta({ label: 'Link kind' })
|
|
10
|
+
|
|
11
|
+
export const EntityLinkSchema = z.object({
|
|
12
|
+
toEntity: EntityIdSchema.meta({ ref: 'entity' }),
|
|
13
|
+
kind: EntityLinkKindSchema,
|
|
14
|
+
via: z.string().trim().min(1).max(255).optional(),
|
|
15
|
+
label: LabelSchema.optional()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
export const EntitySchema = z.object({
|
|
19
|
+
id: EntityIdSchema,
|
|
20
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
21
|
+
order: z.number(),
|
|
22
|
+
label: LabelSchema,
|
|
23
|
+
description: DescriptionSchema.optional(),
|
|
24
|
+
ownedBySystemId: ModelIdSchema.meta({ ref: 'system' }),
|
|
25
|
+
table: z.string().trim().min(1).max(255).optional(),
|
|
26
|
+
rowSchema: ModelIdSchema.optional(),
|
|
27
|
+
stateCatalogId: ModelIdSchema.optional(),
|
|
28
|
+
links: z.array(EntityLinkSchema).optional()
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
export const EntitiesDomainSchema = z
|
|
32
|
+
.record(z.string(), EntitySchema)
|
|
33
|
+
.refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
34
|
+
message: 'Each entity entry id must match its map key'
|
|
35
|
+
})
|
|
36
|
+
.default({})
|
|
37
|
+
|
|
38
|
+
const ENTITY_ENTRY_INPUTS: z.input<typeof EntitySchema>[] = [
|
|
39
|
+
{
|
|
40
|
+
id: 'crm.deal',
|
|
41
|
+
order: 10,
|
|
42
|
+
label: 'Deal',
|
|
43
|
+
description: 'A CRM opportunity or sales pipeline record.',
|
|
44
|
+
ownedBySystemId: 'sales.crm',
|
|
45
|
+
table: 'crm_deals',
|
|
46
|
+
stateCatalogId: 'crm.pipeline',
|
|
47
|
+
links: [{ toEntity: 'crm.contact', kind: 'has-many', via: 'deal_contacts', label: 'contacts' }]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: 'crm.contact',
|
|
51
|
+
order: 20,
|
|
52
|
+
label: 'CRM Contact',
|
|
53
|
+
description: 'A person associated with a CRM relationship or deal.',
|
|
54
|
+
ownedBySystemId: 'sales.crm',
|
|
55
|
+
table: 'crm_contacts'
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'leadgen.list',
|
|
59
|
+
order: 30,
|
|
60
|
+
label: 'Lead List',
|
|
61
|
+
description: 'A prospecting list that groups companies and contacts for acquisition workflows.',
|
|
62
|
+
ownedBySystemId: 'sales.lead-gen',
|
|
63
|
+
table: 'acq_lists',
|
|
64
|
+
links: [
|
|
65
|
+
{ toEntity: 'leadgen.company', kind: 'has-many', via: 'acq_list_companies', label: 'companies' },
|
|
66
|
+
{ toEntity: 'leadgen.contact', kind: 'has-many', via: 'acq_list_members', label: 'contacts' }
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'leadgen.company',
|
|
71
|
+
order: 40,
|
|
72
|
+
label: 'Lead Company',
|
|
73
|
+
description: 'A company record sourced, enriched, and qualified during prospecting.',
|
|
74
|
+
ownedBySystemId: 'sales.lead-gen',
|
|
75
|
+
table: 'acq_list_companies',
|
|
76
|
+
stateCatalogId: 'lead-gen.company',
|
|
77
|
+
links: [
|
|
78
|
+
{ toEntity: 'leadgen.list', kind: 'belongs-to', via: 'list_id', label: 'list' },
|
|
79
|
+
{ toEntity: 'leadgen.contact', kind: 'has-many', via: 'company_id', label: 'contacts' }
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: 'leadgen.contact',
|
|
84
|
+
order: 50,
|
|
85
|
+
label: 'Lead Contact',
|
|
86
|
+
description: 'A prospect contact discovered or enriched during lead generation.',
|
|
87
|
+
ownedBySystemId: 'sales.lead-gen',
|
|
88
|
+
table: 'acq_list_members',
|
|
89
|
+
stateCatalogId: 'lead-gen.contact',
|
|
90
|
+
links: [
|
|
91
|
+
{ toEntity: 'leadgen.list', kind: 'belongs-to', via: 'list_id', label: 'list' },
|
|
92
|
+
{ toEntity: 'leadgen.company', kind: 'belongs-to', via: 'company_id', label: 'company' }
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: 'delivery.project',
|
|
97
|
+
order: 60,
|
|
98
|
+
label: 'Project',
|
|
99
|
+
description: 'A client delivery project.',
|
|
100
|
+
ownedBySystemId: 'projects',
|
|
101
|
+
table: 'projects',
|
|
102
|
+
links: [
|
|
103
|
+
{ toEntity: 'delivery.milestone', kind: 'has-many', via: 'project_id', label: 'milestones' },
|
|
104
|
+
{ toEntity: 'delivery.task', kind: 'has-many', via: 'project_id', label: 'tasks' }
|
|
105
|
+
]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: 'delivery.milestone',
|
|
109
|
+
order: 70,
|
|
110
|
+
label: 'Milestone',
|
|
111
|
+
description: 'A delivery checkpoint within a project.',
|
|
112
|
+
ownedBySystemId: 'projects',
|
|
113
|
+
table: 'project_milestones',
|
|
114
|
+
links: [
|
|
115
|
+
{ toEntity: 'delivery.project', kind: 'belongs-to', via: 'project_id', label: 'project' },
|
|
116
|
+
{ toEntity: 'delivery.task', kind: 'has-many', via: 'milestone_id', label: 'tasks' }
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: 'delivery.task',
|
|
121
|
+
order: 80,
|
|
122
|
+
label: 'Task',
|
|
123
|
+
description: 'A delivery task that can move through the task status catalog.',
|
|
124
|
+
ownedBySystemId: 'projects',
|
|
125
|
+
table: 'project_tasks',
|
|
126
|
+
stateCatalogId: 'delivery.task',
|
|
127
|
+
links: [
|
|
128
|
+
{ toEntity: 'delivery.project', kind: 'belongs-to', via: 'project_id', label: 'project' },
|
|
129
|
+
{ toEntity: 'delivery.milestone', kind: 'belongs-to', via: 'milestone_id', label: 'milestone' }
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
export const DEFAULT_ORGANIZATION_MODEL_ENTITIES: z.infer<typeof EntitiesDomainSchema> = Object.fromEntries(
|
|
135
|
+
ENTITY_ENTRY_INPUTS.map((entity) => {
|
|
136
|
+
const parsed = EntitySchema.parse(entity)
|
|
137
|
+
return [parsed.id, parsed]
|
|
138
|
+
})
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
/** Validate and return a single entity entry. */
|
|
142
|
+
export function defineEntity(entry: z.input<typeof EntitySchema>): z.infer<typeof EntitySchema> {
|
|
143
|
+
return EntitySchema.parse(entry)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Validate and return an id-keyed map of entity entries. */
|
|
147
|
+
export function defineEntities(
|
|
148
|
+
entries: readonly z.input<typeof EntitySchema>[]
|
|
149
|
+
): Record<string, z.infer<typeof EntitySchema>> {
|
|
150
|
+
return defineDomainRecord(EntitySchema, entries)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export type EntityId = z.infer<typeof EntityIdSchema>
|
|
154
|
+
export type EntityLinkKind = z.infer<typeof EntityLinkKindSchema>
|
|
155
|
+
export type EntityLink = z.infer<typeof EntityLinkSchema>
|
|
156
|
+
export type Entity = z.infer<typeof EntitySchema>
|
|
157
|
+
export type EntitiesDomain = z.infer<typeof EntitiesDomainSchema>
|