@elevasis/core 0.18.0 → 0.19.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 (44) hide show
  1. package/dist/index.d.ts +82 -1
  2. package/dist/index.js +291 -171
  3. package/dist/knowledge/index.d.ts +43 -0
  4. package/dist/organization-model/index.d.ts +82 -1
  5. package/dist/organization-model/index.js +291 -171
  6. package/dist/test-utils/index.d.ts +41 -12
  7. package/dist/test-utils/index.js +291 -171
  8. package/package.json +2 -1
  9. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +78 -65
  10. package/src/auth/multi-tenancy/organizations/__tests__/api-schemas.test.ts +194 -0
  11. package/src/auth/multi-tenancy/organizations/api-schemas.ts +136 -128
  12. package/src/business/acquisition/api-schemas.test.ts +100 -2
  13. package/src/business/acquisition/api-schemas.ts +81 -43
  14. package/src/business/acquisition/build-templates.test.ts +212 -0
  15. package/src/business/acquisition/types.ts +21 -38
  16. package/src/execution/engine/index.ts +436 -434
  17. package/src/execution/engine/tools/integration/server/adapters/google-calendar/google-calendar-adapter.ts +428 -0
  18. package/src/execution/engine/tools/integration/server/adapters/google-calendar/index.ts +2 -0
  19. package/src/execution/engine/tools/lead-service-types.ts +51 -9
  20. package/src/execution/engine/tools/platform/acquisition/company-tools.ts +7 -6
  21. package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +6 -5
  22. package/src/execution/engine/tools/platform/acquisition/types.ts +20 -9
  23. package/src/execution/engine/tools/registry.ts +700 -698
  24. package/src/execution/engine/tools/tool-maps.ts +10 -0
  25. package/src/execution/external/__tests__/api-schemas.test.ts +127 -0
  26. package/src/integrations/oauth/__tests__/provider-registry.test.ts +7 -6
  27. package/src/integrations/oauth/provider-registry.ts +74 -61
  28. package/src/integrations/oauth/server/credentials.ts +43 -39
  29. package/src/knowledge/__tests__/queries.test.ts +89 -0
  30. package/src/organization-model/__tests__/icons.test.ts +61 -0
  31. package/src/organization-model/__tests__/knowledge.test.ts +118 -1
  32. package/src/organization-model/__tests__/prospecting-ssot.test.ts +94 -0
  33. package/src/organization-model/defaults.ts +8 -0
  34. package/src/organization-model/domains/knowledge.ts +9 -0
  35. package/src/organization-model/domains/prospecting.ts +272 -226
  36. package/src/organization-model/domains/sales.ts +32 -25
  37. package/src/organization-model/icons.ts +3 -0
  38. package/src/organization-model/types.ts +9 -1
  39. package/src/platform/constants/versions.ts +1 -1
  40. package/src/platform/utils/__tests__/validation.test.ts +1084 -1083
  41. package/src/platform/utils/validation.ts +425 -425
  42. package/src/reference/_generated/contracts.md +78 -65
  43. package/src/server.ts +6 -0
  44. package/src/supabase/database.types.ts +6 -12
@@ -1,11 +1,12 @@
1
- import { z } from 'zod'
2
- import { DescriptionSchema, DisplayMetadataSchema, ModelIdSchema } from './shared'
3
-
4
- export const ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
5
- id: ModelIdSchema,
6
- order: z.number().int().min(0)
7
- })
8
-
1
+ import { z } from 'zod'
2
+ import { LEAD_GEN_STAGE_CATALOG, type LeadGenStageCatalogEntry } from './sales'
3
+ import { DescriptionSchema, DisplayMetadataSchema, ModelIdSchema } from './shared'
4
+
5
+ export const ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
6
+ id: ModelIdSchema,
7
+ order: z.number().int().min(0)
8
+ })
9
+
9
10
  export const ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
10
11
  id: ModelIdSchema,
11
12
  primaryEntity: z.enum(['company', 'contact']),
@@ -16,221 +17,266 @@ export const ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
16
17
  capabilityKey: ModelIdSchema,
17
18
  defaultBatchSize: z.number().int().positive(),
18
19
  maxBatchSize: z.number().int().positive()
19
- }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
20
- message: 'defaultBatchSize must be less than or equal to maxBatchSize',
21
- path: ['defaultBatchSize']
22
- })
23
-
24
- export const ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
25
- id: ModelIdSchema,
26
- steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
27
- })
28
-
29
- export const OrganizationModelProspectingSchema = z.object({
30
- listEntityId: ModelIdSchema,
31
- companyEntityId: ModelIdSchema,
32
- contactEntityId: ModelIdSchema,
33
- description: DescriptionSchema.optional(),
34
- companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
35
- contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
36
- defaultBuildTemplateId: ModelIdSchema,
37
- buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
38
- })
39
-
40
- export const DEFAULT_ORGANIZATION_MODEL_PROSPECTING: z.infer<typeof OrganizationModelProspectingSchema> = {
41
- listEntityId: 'leadgen.list',
42
- companyEntityId: 'leadgen.company',
43
- contactEntityId: 'leadgen.contact',
44
- companyStages: [
45
- { id: 'populated', label: 'Populated', order: 1 },
46
- { id: 'extracted', label: 'Extracted', order: 2 },
47
- { id: 'qualified', label: 'Qualified', order: 3 }
48
- ],
49
- contactStages: [
50
- { id: 'discovered', label: 'Discovered', order: 1 },
51
- { id: 'verified', label: 'Verified', order: 2 },
52
- { id: 'personalized', label: 'Personalized', order: 3 },
53
- { id: 'uploaded', label: 'Uploaded', order: 4 }
54
- ],
55
- defaultBuildTemplateId: 'local-services',
56
- buildTemplates: [
57
- {
58
- id: 'local-services',
59
- label: 'Local Services Prospecting',
60
- description:
61
- 'Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.',
62
- steps: [
63
- {
64
- id: 'source-companies',
65
- label: 'Source companies',
66
- primaryEntity: 'company',
67
- outputs: ['company'],
68
- stageKey: 'populated',
69
- dependencyMode: 'per-record-eligibility',
70
- capabilityKey: 'lead-gen.company.source',
71
- defaultBatchSize: 100,
72
- maxBatchSize: 250
73
- },
74
- {
75
- id: 'analyze-websites',
76
- label: 'Analyze websites',
77
- primaryEntity: 'company',
78
- outputs: ['company'],
79
- stageKey: 'extracted',
80
- dependsOn: ['source-companies'],
81
- dependencyMode: 'per-record-eligibility',
82
- capabilityKey: 'lead-gen.company.website-extract',
83
- defaultBatchSize: 50,
84
- maxBatchSize: 100
85
- },
86
- {
87
- id: 'qualify-companies',
88
- label: 'Qualify companies',
89
- primaryEntity: 'company',
90
- outputs: ['company'],
91
- stageKey: 'qualified',
92
- dependsOn: ['analyze-websites'],
93
- dependencyMode: 'per-record-eligibility',
94
- capabilityKey: 'lead-gen.company.qualify',
95
- defaultBatchSize: 100,
96
- maxBatchSize: 250
97
- },
98
- {
99
- id: 'find-contacts',
100
- label: 'Find contacts',
101
- primaryEntity: 'contact',
102
- outputs: ['contact'],
103
- stageKey: 'discovered',
104
- dependsOn: ['qualify-companies'],
105
- dependencyMode: 'per-record-eligibility',
106
- capabilityKey: 'lead-gen.contact.discover',
107
- defaultBatchSize: 50,
108
- maxBatchSize: 100
109
- },
110
- {
111
- id: 'verify-emails',
112
- label: 'Verify emails',
113
- primaryEntity: 'contact',
114
- outputs: ['contact'],
115
- stageKey: 'verified',
116
- dependsOn: ['find-contacts'],
117
- dependencyMode: 'per-record-eligibility',
118
- capabilityKey: 'lead-gen.contact.verify-email',
119
- defaultBatchSize: 100,
120
- maxBatchSize: 500
121
- },
122
- {
123
- id: 'personalize',
124
- label: 'Personalize',
125
- primaryEntity: 'contact',
126
- outputs: ['contact'],
127
- stageKey: 'personalized',
128
- dependsOn: ['verify-emails'],
129
- dependencyMode: 'per-record-eligibility',
130
- capabilityKey: 'lead-gen.contact.personalize',
131
- defaultBatchSize: 25,
132
- maxBatchSize: 100
133
- },
134
- {
135
- id: 'review',
136
- label: 'Review',
137
- primaryEntity: 'contact',
138
- outputs: ['export'],
139
- stageKey: 'uploaded',
140
- dependsOn: ['personalize'],
141
- dependencyMode: 'per-record-eligibility',
142
- capabilityKey: 'lead-gen.review.outreach-ready',
143
- defaultBatchSize: 25,
144
- maxBatchSize: 100
145
- }
146
- ]
147
- },
148
- {
149
- id: 'dtc-subscription-apollo-clickup',
150
- label: 'DTC Subscription Apollo Export',
151
- description:
152
- 'Prospecting pipeline for DTC subscription or subscription-ready brands where Apollo is the source and contact-enrichment layer, Elevasis handles company research and fit scoring, and approved leads export as an approved lead list.',
153
- steps: [
154
- {
155
- id: 'import-apollo-search',
156
- label: 'Import Apollo search',
157
- description: 'Pull companies and seed contact data from a predefined Apollo search or list.',
158
- primaryEntity: 'company',
159
- outputs: ['company', 'contact'],
160
- stageKey: 'populated',
161
- dependencyMode: 'per-record-eligibility',
162
- capabilityKey: 'lead-gen.company.apollo-import',
163
- defaultBatchSize: 250,
164
- maxBatchSize: 1000
165
- },
166
- {
167
- id: 'analyze-websites',
168
- label: 'Analyze websites',
169
- description: 'Extract subscription, product, retention, and tech-stack signals from each brand website.',
170
- primaryEntity: 'company',
171
- outputs: ['company'],
172
- stageKey: 'extracted',
173
- dependsOn: ['import-apollo-search'],
174
- dependencyMode: 'per-record-eligibility',
175
- capabilityKey: 'lead-gen.company.website-extract',
176
- defaultBatchSize: 50,
177
- maxBatchSize: 100
178
- },
179
- {
180
- id: 'score-dtc-fit',
181
- label: 'Score DTC fit',
182
- description:
183
- 'Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.',
184
- primaryEntity: 'company',
185
- outputs: ['company'],
186
- stageKey: 'qualified',
187
- dependsOn: ['analyze-websites'],
188
- dependencyMode: 'per-record-eligibility',
189
- capabilityKey: 'lead-gen.company.dtc-subscription-qualify',
190
- defaultBatchSize: 100,
191
- maxBatchSize: 250
192
- },
193
- {
194
- id: 'enrich-decision-makers',
195
- label: 'Enrich decision-makers',
196
- description:
197
- 'Use Apollo to find qualified contacts such as founders, retention leads, lifecycle leads, and marketing owners.',
198
- primaryEntity: 'contact',
199
- outputs: ['contact'],
200
- stageKey: 'discovered',
201
- dependsOn: ['score-dtc-fit'],
202
- dependencyMode: 'per-record-eligibility',
203
- capabilityKey: 'lead-gen.contact.apollo-decision-maker-enrich',
204
- defaultBatchSize: 100,
205
- maxBatchSize: 250
206
- },
207
- {
208
- id: 'verify-emails',
209
- label: 'Verify emails',
210
- description: 'Verify deliverability before the QC and handoff step.',
211
- primaryEntity: 'contact',
212
- outputs: ['contact'],
213
- stageKey: 'verified',
214
- dependsOn: ['enrich-decision-makers'],
215
- dependencyMode: 'per-record-eligibility',
216
- capabilityKey: 'lead-gen.contact.verify-email',
217
- defaultBatchSize: 250,
218
- maxBatchSize: 500
219
- },
220
- {
221
- id: 'review-and-export',
222
- label: 'Review and export',
223
- description: 'Operator QC approves or rejects leads, then approved records are exported as a lead list.',
224
- primaryEntity: 'company',
225
- outputs: ['export'],
226
- stageKey: 'uploaded',
227
- dependsOn: ['verify-emails'],
228
- dependencyMode: 'per-record-eligibility',
229
- capabilityKey: 'lead-gen.export.list',
230
- defaultBatchSize: 100,
231
- maxBatchSize: 250
232
- }
233
- ]
234
- }
235
- ]
236
- }
20
+ }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
21
+ message: 'defaultBatchSize must be less than or equal to maxBatchSize',
22
+ path: ['defaultBatchSize']
23
+ })
24
+
25
+ export const ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
26
+ id: ModelIdSchema,
27
+ steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
28
+ })
29
+
30
+ export type ListBuilderStep = z.infer<typeof ProspectingBuildTemplateStepSchema>
31
+ export type TemplateName = 'localServices' | 'dtcApolloClickup'
32
+ export type StepName = string
33
+ export type CapabilityRegistry = Record<string, string>
34
+
35
+ export const CAPABILITY_REGISTRY = {
36
+ 'lead-gen.company.source': 'lgn-import-workflow',
37
+ 'lead-gen.company.apollo-import': 'lgn-01c-apollo-import-workflow',
38
+ 'lead-gen.contact.discover': 'lgn-04-email-discovery-workflow',
39
+ 'lead-gen.contact.verify-email': 'lgn-05-email-verification-workflow',
40
+ 'lead-gen.company.website-extract': 'lgn-02-website-extract-workflow',
41
+ 'lead-gen.company.qualify': 'lgn-03-company-qualification-workflow',
42
+ 'lead-gen.company.dtc-subscription-qualify': 'lgn-03b-dtc-subscription-score-workflow',
43
+ 'lead-gen.contact.apollo-decision-maker-enrich': 'lgn-04b-apollo-decision-maker-enrich-workflow',
44
+ 'lead-gen.contact.personalize': 'ist-personalization-workflow',
45
+ 'lead-gen.review.outreach-ready': 'ist-upload-contacts-workflow',
46
+ 'lead-gen.export.list': 'lgn-06-export-list-workflow',
47
+ 'lead-gen.company.cleanup': 'lgn-company-cleanup-workflow'
48
+ } as const satisfies CapabilityRegistry
49
+
50
+ export const PROSPECTING_STEPS = {
51
+ localServices: {
52
+ sourceCompanies: {
53
+ id: 'source-companies',
54
+ label: 'Companies found',
55
+ primaryEntity: 'company',
56
+ outputs: ['company'],
57
+ stageKey: 'populated',
58
+ dependencyMode: 'per-record-eligibility',
59
+ capabilityKey: 'lead-gen.company.source',
60
+ defaultBatchSize: 100,
61
+ maxBatchSize: 250
62
+ },
63
+ analyzeWebsites: {
64
+ id: 'analyze-websites',
65
+ label: 'Websites analyzed',
66
+ primaryEntity: 'company',
67
+ outputs: ['company'],
68
+ stageKey: 'extracted',
69
+ dependsOn: ['source-companies'],
70
+ dependencyMode: 'per-record-eligibility',
71
+ capabilityKey: 'lead-gen.company.website-extract',
72
+ defaultBatchSize: 50,
73
+ maxBatchSize: 100
74
+ },
75
+ qualifyCompanies: {
76
+ id: 'qualify-companies',
77
+ label: 'Companies qualified',
78
+ primaryEntity: 'company',
79
+ outputs: ['company'],
80
+ stageKey: 'qualified',
81
+ dependsOn: ['analyze-websites'],
82
+ dependencyMode: 'per-record-eligibility',
83
+ capabilityKey: 'lead-gen.company.qualify',
84
+ defaultBatchSize: 100,
85
+ maxBatchSize: 250
86
+ },
87
+ findContacts: {
88
+ id: 'find-contacts',
89
+ label: 'Decision-makers found',
90
+ primaryEntity: 'contact',
91
+ outputs: ['contact'],
92
+ stageKey: 'discovered',
93
+ dependsOn: ['qualify-companies'],
94
+ dependencyMode: 'per-record-eligibility',
95
+ capabilityKey: 'lead-gen.contact.discover',
96
+ defaultBatchSize: 50,
97
+ maxBatchSize: 100
98
+ },
99
+ verifyEmails: {
100
+ id: 'verify-emails',
101
+ label: 'Emails verified',
102
+ primaryEntity: 'contact',
103
+ outputs: ['contact'],
104
+ stageKey: 'verified',
105
+ dependsOn: ['find-contacts'],
106
+ dependencyMode: 'per-record-eligibility',
107
+ capabilityKey: 'lead-gen.contact.verify-email',
108
+ defaultBatchSize: 100,
109
+ maxBatchSize: 500
110
+ },
111
+ personalize: {
112
+ id: 'personalize',
113
+ label: 'Personalize',
114
+ primaryEntity: 'contact',
115
+ outputs: ['contact'],
116
+ stageKey: 'personalized',
117
+ dependsOn: ['verify-emails'],
118
+ dependencyMode: 'per-record-eligibility',
119
+ capabilityKey: 'lead-gen.contact.personalize',
120
+ defaultBatchSize: 25,
121
+ maxBatchSize: 100
122
+ },
123
+ review: {
124
+ id: 'review',
125
+ label: 'Reviewed and exported',
126
+ primaryEntity: 'contact',
127
+ outputs: ['export'],
128
+ stageKey: 'uploaded',
129
+ dependsOn: ['personalize'],
130
+ dependencyMode: 'per-record-eligibility',
131
+ capabilityKey: 'lead-gen.review.outreach-ready',
132
+ defaultBatchSize: 25,
133
+ maxBatchSize: 100
134
+ }
135
+ },
136
+ dtcApolloClickup: {
137
+ importApolloSearch: {
138
+ id: 'import-apollo-search',
139
+ label: 'Companies found',
140
+ description: 'Pull companies and seed contact data from a predefined Apollo search or list.',
141
+ primaryEntity: 'company',
142
+ outputs: ['company', 'contact'],
143
+ stageKey: 'populated',
144
+ dependencyMode: 'per-record-eligibility',
145
+ capabilityKey: 'lead-gen.company.apollo-import',
146
+ defaultBatchSize: 250,
147
+ maxBatchSize: 1000
148
+ },
149
+ analyzeWebsites: {
150
+ id: 'analyze-websites',
151
+ label: 'Websites analyzed',
152
+ description: 'Extract subscription, product, retention, and tech-stack signals from each brand website.',
153
+ primaryEntity: 'company',
154
+ outputs: ['company'],
155
+ stageKey: 'extracted',
156
+ dependsOn: ['import-apollo-search'],
157
+ dependencyMode: 'per-record-eligibility',
158
+ capabilityKey: 'lead-gen.company.website-extract',
159
+ defaultBatchSize: 50,
160
+ maxBatchSize: 100
161
+ },
162
+ scoreDtcFit: {
163
+ id: 'score-dtc-fit',
164
+ label: 'Companies qualified',
165
+ description: 'Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.',
166
+ primaryEntity: 'company',
167
+ outputs: ['company'],
168
+ stageKey: 'qualified',
169
+ dependsOn: ['analyze-websites'],
170
+ dependencyMode: 'per-record-eligibility',
171
+ capabilityKey: 'lead-gen.company.dtc-subscription-qualify',
172
+ defaultBatchSize: 100,
173
+ maxBatchSize: 250
174
+ },
175
+ enrichDecisionMakers: {
176
+ id: 'enrich-decision-makers',
177
+ label: 'Decision-makers found',
178
+ description:
179
+ 'Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.',
180
+ primaryEntity: 'company',
181
+ outputs: ['contact'],
182
+ stageKey: 'decision-makers-enriched',
183
+ dependsOn: ['score-dtc-fit'],
184
+ dependencyMode: 'per-record-eligibility',
185
+ capabilityKey: 'lead-gen.contact.apollo-decision-maker-enrich',
186
+ defaultBatchSize: 100,
187
+ maxBatchSize: 250
188
+ },
189
+ verifyEmails: {
190
+ id: 'verify-emails',
191
+ label: 'Emails verified',
192
+ description: 'Verify deliverability before the QC and handoff step.',
193
+ primaryEntity: 'contact',
194
+ outputs: ['contact'],
195
+ stageKey: 'verified',
196
+ dependsOn: ['enrich-decision-makers'],
197
+ dependencyMode: 'per-record-eligibility',
198
+ capabilityKey: 'lead-gen.contact.verify-email',
199
+ defaultBatchSize: 250,
200
+ maxBatchSize: 500
201
+ },
202
+ reviewAndExport: {
203
+ id: 'review-and-export',
204
+ label: 'Reviewed and exported',
205
+ description: 'Operator QC approves or rejects leads, then approved records are exported as a lead list.',
206
+ primaryEntity: 'company',
207
+ outputs: ['export'],
208
+ stageKey: 'uploaded',
209
+ dependsOn: ['verify-emails'],
210
+ dependencyMode: 'per-record-eligibility',
211
+ capabilityKey: 'lead-gen.export.list',
212
+ defaultBatchSize: 100,
213
+ maxBatchSize: 250
214
+ }
215
+ }
216
+ } as const satisfies Record<TemplateName, Record<StepName, ListBuilderStep>>
217
+
218
+ export const OrganizationModelProspectingSchema = z.object({
219
+ listEntityId: ModelIdSchema,
220
+ companyEntityId: ModelIdSchema,
221
+ contactEntityId: ModelIdSchema,
222
+ description: DescriptionSchema.optional(),
223
+ companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
224
+ contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
225
+ defaultBuildTemplateId: ModelIdSchema,
226
+ buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
227
+ })
228
+
229
+ function toProspectingLifecycleStage(stage: LeadGenStageCatalogEntry): z.infer<typeof ProspectingLifecycleStageSchema> {
230
+ return {
231
+ id: stage.key,
232
+ label: stage.label,
233
+ order: stage.order
234
+ }
235
+ }
236
+
237
+ function leadGenStagesForEntity(entity: LeadGenStageCatalogEntry['entity']): z.infer<typeof ProspectingLifecycleStageSchema>[] {
238
+ return Object.values(LEAD_GEN_STAGE_CATALOG)
239
+ .filter((stage) => stage.entity === entity)
240
+ .sort((a, b) => a.order - b.order)
241
+ .map(toProspectingLifecycleStage)
242
+ }
243
+
244
+ export const DEFAULT_ORGANIZATION_MODEL_PROSPECTING: z.infer<typeof OrganizationModelProspectingSchema> = {
245
+ listEntityId: 'leadgen.list',
246
+ companyEntityId: 'leadgen.company',
247
+ contactEntityId: 'leadgen.contact',
248
+ companyStages: leadGenStagesForEntity('company'),
249
+ contactStages: leadGenStagesForEntity('contact'),
250
+ defaultBuildTemplateId: 'local-services',
251
+ buildTemplates: [
252
+ {
253
+ id: 'local-services',
254
+ label: 'Local Services Prospecting',
255
+ description:
256
+ 'Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.',
257
+ steps: [
258
+ PROSPECTING_STEPS.localServices.sourceCompanies,
259
+ PROSPECTING_STEPS.localServices.analyzeWebsites,
260
+ PROSPECTING_STEPS.localServices.qualifyCompanies,
261
+ PROSPECTING_STEPS.localServices.findContacts,
262
+ PROSPECTING_STEPS.localServices.verifyEmails,
263
+ PROSPECTING_STEPS.localServices.personalize,
264
+ PROSPECTING_STEPS.localServices.review
265
+ ]
266
+ },
267
+ {
268
+ id: 'dtc-subscription-apollo-clickup',
269
+ label: 'DTC Subscription Apollo Export',
270
+ description:
271
+ 'Prospecting pipeline for DTC subscription or subscription-ready brands where Apollo is the source and contact-enrichment layer, Elevasis handles company research and fit scoring, and approved leads export as an approved lead list.',
272
+ steps: [
273
+ PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
274
+ PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
275
+ PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
276
+ PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
277
+ PROSPECTING_STEPS.dtcApolloClickup.verifyEmails,
278
+ PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
279
+ ]
280
+ }
281
+ ]
282
+ }
@@ -440,21 +440,21 @@ export const LEAD_GEN_PIPELINE_DEFINITIONS: Record<string, StatefulPipelineDefin
440
440
  }
441
441
 
442
442
  // ============================================================================
443
- // Lead-Gen Stage Catalog (status-based processing model)
443
+ // Lead-Gen Stage Catalog (OM Spine processing-state model)
444
444
  //
445
- // Canonical set of processing stage keys for the status-map model that replaces
446
- // the stateful trait on acq_list_members and acq_list_companies. Each key maps
447
- // to a terminal status string in the processing_state jsonb column.
445
+ // Canonical set of processing stage keys for acq_companies.processing_state and
446
+ // acq_contacts.processing_state. These keys coordinate build templates, workflow
447
+ // factory validation, API filters, and UI progress projections.
448
448
  //
449
- // Sources:
449
+ // State is sparse: absent keys mean "not attempted"; present keys hold terminal
450
+ // status entries such as success, no_result, skipped, or error.
451
+ //
452
+ // Historical sources:
450
453
  // ACQ_LIST_MEMBERS_LEAD_GEN_PIPELINE → personalized, uploaded, interested,
451
454
  // discovered, verified
452
455
  // ACQ_LIST_COMPANIES_LEAD_GEN_PIPELINE → populated, extracted, qualified
453
456
  // Design plan hint (lead-gen-domain-cleanup.mdx §4) → scraped, enriched
454
457
  //
455
- // Wave 2 will validate pipeline_config.stages[].key against this catalog at
456
- // list-create/update time. Each lead-gen workflow in operations will declare
457
- // stageImplemented: '<key>' in its WorkflowDefinition (Slice D-2).
458
458
  // ============================================================================
459
459
 
460
460
  /** One entry in the lead-gen stage catalog. */
@@ -488,15 +488,15 @@ export const LEAD_GEN_STAGE_CATALOG: Record<string, LeadGenStageCatalogEntry> =
488
488
  },
489
489
  populated: {
490
490
  key: 'populated',
491
- label: 'Populated',
492
- description: 'Company record populated with structured data from scrape results.',
491
+ label: 'Companies found',
492
+ description: 'Companies have been found and added to the lead-gen list.',
493
493
  order: 2,
494
494
  entity: 'company'
495
495
  },
496
496
  extracted: {
497
497
  key: 'extracted',
498
- label: 'Extracted',
499
- description: 'Website content extracted and parsed for company intelligence.',
498
+ label: 'Websites analyzed',
499
+ description: 'Company websites have been analyzed for business signals.',
500
500
  order: 3,
501
501
  entity: 'company'
502
502
  },
@@ -507,29 +507,36 @@ export const LEAD_GEN_STAGE_CATALOG: Record<string, LeadGenStageCatalogEntry> =
507
507
  order: 4,
508
508
  entity: 'company'
509
509
  },
510
+ 'decision-makers-enriched': {
511
+ key: 'decision-makers-enriched',
512
+ label: 'Decision-makers found',
513
+ description: 'Decision-maker contacts discovered and attached to a qualified company.',
514
+ order: 6,
515
+ entity: 'company'
516
+ },
510
517
 
511
518
  // Prospecting — contact discovery
512
519
  discovered: {
513
520
  key: 'discovered',
514
- label: 'Discovered',
515
- description: 'Contact email address discovered via an email-discovery workflow.',
521
+ label: 'Decision-makers found',
522
+ description: 'Decision-maker contact details have been found.',
516
523
  order: 5,
517
524
  entity: 'contact'
518
525
  },
519
526
  verified: {
520
527
  key: 'verified',
521
- label: 'Verified',
522
- description: 'Contact email address verified as deliverable (email verification workflow).',
523
- order: 6,
528
+ label: 'Emails verified',
529
+ description: 'Contact email addresses have been checked for deliverability.',
530
+ order: 7,
524
531
  entity: 'contact'
525
532
  },
526
533
 
527
534
  // Qualification
528
535
  qualified: {
529
536
  key: 'qualified',
530
- label: 'Qualified',
531
- description: 'Company passed the ICP qualification rubric (company-qualification workflow).',
532
- order: 7,
537
+ label: 'Companies qualified',
538
+ description: 'Companies have been scored against the qualification criteria.',
539
+ order: 8,
533
540
  entity: 'company'
534
541
  },
535
542
 
@@ -538,21 +545,21 @@ export const LEAD_GEN_STAGE_CATALOG: Record<string, LeadGenStageCatalogEntry> =
538
545
  key: 'personalized',
539
546
  label: 'Personalized',
540
547
  description: 'Outreach message personalized for the contact (Instantly personalization workflow).',
541
- order: 8,
548
+ order: 9,
542
549
  entity: 'contact'
543
550
  },
544
551
  uploaded: {
545
552
  key: 'uploaded',
546
- label: 'Uploaded',
547
- description: 'Contact uploaded to an Instantly campaign for outreach.',
548
- order: 9,
553
+ label: 'Reviewed and exported',
554
+ description: 'Approved records have been reviewed and exported for handoff.',
555
+ order: 10,
549
556
  entity: 'contact'
550
557
  },
551
558
  interested: {
552
559
  key: 'interested',
553
560
  label: 'Interested',
554
561
  description: 'Contact replied with a positive signal (Instantly reply-handler transition).',
555
- order: 10,
562
+ order: 11,
556
563
  entity: 'contact'
557
564
  }
558
565
  }