@elevasis/core 0.13.0 → 0.14.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 (41) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +9 -2
  3. package/dist/organization-model/index.d.ts +1 -1
  4. package/dist/organization-model/index.js +9 -2
  5. package/dist/test-utils/index.d.ts +463 -377
  6. package/dist/test-utils/index.js +9 -2
  7. package/package.json +1 -1
  8. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +2324 -0
  9. package/src/business/acquisition/activity-events.test.ts +250 -0
  10. package/src/business/acquisition/activity-events.ts +7 -65
  11. package/src/business/acquisition/api-schemas.test.ts +1180 -0
  12. package/src/business/acquisition/api-schemas.ts +1075 -859
  13. package/src/business/acquisition/crm-state-actions.test.ts +160 -0
  14. package/src/business/acquisition/derive-actions.test.ts +518 -0
  15. package/src/business/acquisition/derive-actions.ts +103 -90
  16. package/src/business/acquisition/index.ts +149 -111
  17. package/src/business/acquisition/stateful.ts +30 -0
  18. package/src/business/acquisition/types.ts +44 -77
  19. package/src/execution/engine/index.ts +437 -434
  20. package/src/execution/engine/tools/integration/server/adapters/attio/__tests__/attio-crud.integration.test.ts +363 -360
  21. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.test.ts +162 -186
  22. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.test.ts +316 -338
  23. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-adapter.ts +204 -210
  24. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.test.ts +88 -0
  25. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.ts +141 -134
  26. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/utils/types.ts +76 -75
  27. package/src/execution/engine/tools/integration/service.test.ts +34 -9
  28. package/src/execution/engine/tools/integration/service.ts +6 -3
  29. package/src/execution/engine/tools/lead-service-types.ts +945 -888
  30. package/src/execution/engine/tools/platform/acquisition/types.ts +266 -260
  31. package/src/execution/engine/tools/registry.ts +701 -699
  32. package/src/execution/engine/tools/tool-maps.ts +816 -791
  33. package/src/execution/engine/workflow/types.ts +11 -0
  34. package/src/organization-model/contracts.ts +4 -4
  35. package/src/organization-model/domains/navigation.ts +62 -62
  36. package/src/organization-model/domains/sales.ts +272 -0
  37. package/src/organization-model/published.ts +21 -21
  38. package/src/organization-model/resolve.ts +21 -8
  39. package/src/platform/constants/versions.ts +1 -1
  40. package/src/reference/_generated/contracts.md +2324 -0
  41. package/src/supabase/database.types.ts +2958 -2886
@@ -1,90 +1,103 @@
1
- import type { AcqDealRow } from './types'
2
-
3
- export interface Action {
4
- key: string
5
- label: string
6
- kind: 'transition' | 'edit' | 'modal'
7
- payload?: Record<string, unknown>
8
- }
9
-
10
- // Stage order inlined from DEFAULT_ORGANIZATION_MODEL_SALES (single caller).
11
- // Update here if the default pipeline changes.
12
- const STAGE_ORDER = ['interested', 'proposal', 'closing', 'closed_won', 'closed_lost', 'nurturing'] as const
13
-
14
- type DefaultStageKey = (typeof STAGE_ORDER)[number]
15
-
16
- function isDefaultStage(key: string | null | undefined): key is DefaultStageKey {
17
- return STAGE_ORDER.includes(key as DefaultStageKey)
18
- }
19
-
20
- function transitionAction(stageKey: DefaultStageKey): Action {
21
- const labels: Record<DefaultStageKey, string> = {
22
- interested: 'Move to Interested',
23
- proposal: 'Move to Proposal',
24
- closing: 'Move to Closing',
25
- closed_won: 'Close Won',
26
- closed_lost: 'Close Lost',
27
- nurturing: 'Move to Nurturing'
28
- }
29
- return {
30
- key: `move_to_${stageKey}`,
31
- label: labels[stageKey],
32
- kind: 'transition',
33
- payload: { stageKey }
34
- }
35
- }
36
-
37
- function interestedActions(stateKey: string | null | undefined): Action[] {
38
- const base: Action[] = [transitionAction('proposal'), transitionAction('closed_lost'), transitionAction('nurturing')]
39
-
40
- if (stateKey === 'discovery_replied') {
41
- return [...base, { key: 'send_link', label: 'Send Booking Link', kind: 'modal' }]
42
- }
43
-
44
- if (stateKey === 'discovery_link_sent') {
45
- return [...base, { key: 'send_nudge', label: 'Send Nudge', kind: 'modal' }]
46
- }
47
-
48
- if (stateKey === 'discovery_nudging') {
49
- return [
50
- ...base,
51
- { key: 'send_nudge', label: 'Send Nudge', kind: 'modal' },
52
- { key: 'mark_no_show', label: 'Mark No-Show', kind: 'transition' }
53
- ]
54
- }
55
-
56
- if (stateKey === 'discovery_booking_cancelled') {
57
- return [...base, { key: 'rebook', label: 'Rebook', kind: 'modal' }]
58
- }
59
-
60
- return base
61
- }
62
-
63
- function proposalActions(): Action[] {
64
- return [transitionAction('closing'), transitionAction('closed_lost'), transitionAction('nurturing')]
65
- }
66
-
67
- function closingActions(): Action[] {
68
- return [transitionAction('closed_won'), transitionAction('closed_lost'), transitionAction('nurturing')]
69
- }
70
-
71
- export function deriveActions(deal: AcqDealRow): Action[] {
72
- const stage = deal.stage_key
73
-
74
- if (!isDefaultStage(stage)) {
75
- return []
76
- }
77
-
78
- switch (stage) {
79
- case 'interested':
80
- return interestedActions(deal.state_key)
81
- case 'proposal':
82
- return proposalActions()
83
- case 'closing':
84
- return closingActions()
85
- case 'closed_won':
86
- case 'closed_lost':
87
- case 'nurturing':
88
- return []
89
- }
90
- }
1
+ import { z } from 'zod'
2
+ import type { AcqDealRow } from './types'
3
+
4
+ export interface Action {
5
+ key: string
6
+ label: string
7
+ payloadSchema?: z.ZodTypeAny
8
+ }
9
+
10
+ export interface ActionDef {
11
+ key: string
12
+ label: string
13
+ isAvailableFor: (deal: AcqDealRow) => boolean
14
+ workflowId: string
15
+ payloadSchema?: z.ZodTypeAny
16
+ }
17
+
18
+ export const SendReplyActionPayloadSchema = z
19
+ .object({
20
+ replyBody: z.string().trim().min(1).max(10000)
21
+ })
22
+ .strict()
23
+
24
+ export const DEFAULT_CRM_ACTIONS: ActionDef[] = [
25
+ {
26
+ key: 'move_to_proposal',
27
+ label: 'Move to Proposal',
28
+ isAvailableFor: (deal) => deal.stage_key === 'interested',
29
+ workflowId: 'move_to_proposal-workflow'
30
+ },
31
+ {
32
+ key: 'move_to_closing',
33
+ label: 'Move to Closing',
34
+ isAvailableFor: (deal) => deal.stage_key === 'proposal',
35
+ workflowId: 'move_to_closing-workflow'
36
+ },
37
+ {
38
+ key: 'move_to_closed_won',
39
+ label: 'Close Won',
40
+ isAvailableFor: (deal) => deal.stage_key === 'closing',
41
+ workflowId: 'move_to_closed_won-workflow'
42
+ },
43
+ {
44
+ key: 'move_to_closed_lost',
45
+ label: 'Close Lost',
46
+ isAvailableFor: (deal) =>
47
+ deal.stage_key === 'interested' || deal.stage_key === 'proposal' || deal.stage_key === 'closing',
48
+ workflowId: 'move_to_closed_lost-workflow'
49
+ },
50
+ {
51
+ key: 'move_to_nurturing',
52
+ label: 'Move to Nurturing',
53
+ isAvailableFor: (deal) =>
54
+ deal.stage_key === 'interested' || deal.stage_key === 'proposal' || deal.stage_key === 'closing',
55
+ workflowId: 'move_to_nurturing-workflow'
56
+ },
57
+ {
58
+ key: 'send_reply',
59
+ label: 'Send Reply',
60
+ isAvailableFor: (deal) =>
61
+ deal.stage_key === 'interested' &&
62
+ (deal.state_key === 'discovery_replied' ||
63
+ deal.state_key === 'discovery_link_sent' ||
64
+ deal.state_key === 'discovery_nudging'),
65
+ workflowId: 'crm-send-reply-workflow',
66
+ payloadSchema: SendReplyActionPayloadSchema
67
+ },
68
+ {
69
+ key: 'send_link',
70
+ label: 'Send Booking Link',
71
+ isAvailableFor: (deal) => deal.stage_key === 'interested' && deal.state_key === 'discovery_replied',
72
+ workflowId: 'crm-send-booking-link-workflow'
73
+ },
74
+ {
75
+ key: 'send_nudge',
76
+ label: 'Send Nudge',
77
+ isAvailableFor: (deal) =>
78
+ deal.stage_key === 'interested' &&
79
+ (deal.state_key === 'discovery_link_sent' || deal.state_key === 'discovery_nudging'),
80
+ workflowId: 'crm-send-nudge-workflow'
81
+ },
82
+ {
83
+ key: 'mark_no_show',
84
+ label: 'Mark No-Show',
85
+ isAvailableFor: (deal) => deal.stage_key === 'interested' && deal.state_key === 'discovery_nudging',
86
+ // Mirrors the auto-timeout precedent in operations/sales/crm/pipeline/timeout-actions.ts:
87
+ // both manual-click and timeout move the deal to closed_lost. The action_taken activity
88
+ // event captures operator intent and distinguishes the manual variant from the timed one.
89
+ workflowId: 'mark_no_show-workflow'
90
+ },
91
+ {
92
+ key: 'rebook',
93
+ label: 'Rebook',
94
+ isAvailableFor: (deal) => deal.stage_key === 'interested' && deal.state_key === 'discovery_booking_cancelled',
95
+ workflowId: 'crm-rebook-workflow'
96
+ }
97
+ ]
98
+
99
+ export function deriveActions(deal: AcqDealRow, actions: ActionDef[] = DEFAULT_CRM_ACTIONS): Action[] {
100
+ return actions
101
+ .filter((a) => a.isAvailableFor(deal))
102
+ .map(({ key, label, payloadSchema }) => ({ key, label, payloadSchema }))
103
+ }
@@ -1,111 +1,149 @@
1
- export * from './types'
2
- export * from './activity-events'
3
- export * from './derive-actions'
4
- // Export api-schemas selectively to avoid re-exporting names already defined in types.ts
5
- // (DealStage, AcqDealTaskKind are declared as union types there; api-schemas re-infers them from Zod)
6
- export {
7
- AcqCompanyStatusSchema,
8
- AcqContactStatusSchema,
9
- AcqEmailValidSchema,
10
- CompanyIdParamsSchema,
11
- ContactIdParamsSchema,
12
- ListCompaniesQuerySchema,
13
- ListContactsQuerySchema,
14
- CreateCompanyRequestSchema,
15
- UpdateCompanyRequestSchema,
16
- CreateContactRequestSchema,
17
- UpdateContactRequestSchema,
18
- AcqCompanyResponseSchema,
19
- AcqCompanyListResponseSchema,
20
- AcqContactResponseSchema,
21
- AcqContactListResponseSchema,
22
- AcqCompanySchemas,
23
- AcqContactSchemas,
24
- DealStageSchema,
25
- AcqDealTaskKindSchema,
26
- DealIdParamsSchema,
27
- DealTaskIdParamsSchema,
28
- ListDealsQuerySchema,
29
- ListDealTasksDueQuerySchema,
30
- CreateDealNoteRequestSchema,
31
- CreateDealTaskRequestSchema,
32
- TransitionItemRequestSchema,
33
- DealContactSummarySchema,
34
- DealListItemSchema,
35
- DealListResponseSchema,
36
- DealDetailResponseSchema,
37
- DealNoteResponseSchema,
38
- DealNoteListResponseSchema,
39
- DealTaskResponseSchema,
40
- DealTaskListResponseSchema,
41
- DealSchemas,
42
- ListQualificationSchema,
43
- ListEnrichmentSchema,
44
- ListPersonalizationSchema,
45
- PipelineStepSchema,
46
- ListPipelineSchema,
47
- ListConfigSchema,
48
- ListStageCountsSchema,
49
- ListTelemetrySchema,
50
- ListIdParamsSchema,
51
- CreateListRequestSchema,
52
- UpdateListRequestSchema,
53
- UpdateListConfigRequestSchema,
54
- AddCompaniesToListRequestSchema,
55
- RemoveCompaniesFromListRequestSchema,
56
- AddContactsToListRequestSchema,
57
- RecordListExecutionRequestSchema,
58
- AcqListResponseSchema,
59
- AcqListListResponseSchema,
60
- ListTelemetryResponseSchema,
61
- ListTelemetryListResponseSchema,
62
- ListExecutionSummarySchema,
63
- ListExecutionsResponseSchema,
64
- AcqListSchemas,
65
- type CompanyIdParams,
66
- type ContactIdParams,
67
- type ListCompaniesQuery,
68
- type ListContactsQuery,
69
- type CreateCompanyRequest,
70
- type UpdateCompanyRequest,
71
- type CreateContactRequest,
72
- type UpdateContactRequest,
73
- type AcqCompanyResponse,
74
- type AcqCompanyListResponse,
75
- type AcqContactResponse,
76
- type AcqContactListResponse,
77
- type AcqCompanyStatus,
78
- type AcqContactStatus,
79
- type AcqEmailValid,
80
- type DealIdParams,
81
- type DealTaskIdParams,
82
- type ListDealsQuery,
83
- type ListDealTasksDueQuery,
84
- type CreateDealNoteRequest,
85
- type CreateDealTaskRequest,
86
- type TransitionItemRequest,
87
- type DealListResponse,
88
- type DealDetailResponse,
89
- type DealNoteResponse,
90
- type DealNoteListResponse,
91
- type DealTaskResponse,
92
- type DealTaskListResponse,
93
- type ListConfigInput,
94
- type ListStageCountsInput,
95
- type ListTelemetryInput,
96
- type PipelineStepInput,
97
- type ListIdParams,
98
- type CreateListRequest,
99
- type UpdateListRequest,
100
- type UpdateListConfigRequest,
101
- type AddCompaniesToListRequest,
102
- type RemoveCompaniesFromListRequest,
103
- type AddContactsToListRequest,
104
- type RecordListExecutionRequest,
105
- type AcqListResponse,
106
- type AcqListListResponse,
107
- type ListTelemetryResponse,
108
- type ListTelemetryListResponse,
109
- type ListExecutionSummaryInput,
110
- type ListExecutionsResponse
111
- } from './api-schemas'
1
+ export * from './types'
2
+ export * from './activity-events'
3
+ export * from './derive-actions'
4
+ export * from './stateful'
5
+ // Export api-schemas selectively to avoid re-exporting names already defined in types.ts
6
+ // (DealStage, AcqDealTaskKind are declared as union types there; api-schemas re-infers them from Zod)
7
+ export {
8
+ AcqCompanyStatusSchema,
9
+ AcqContactStatusSchema,
10
+ AcqEmailValidSchema,
11
+ CompanyIdParamsSchema,
12
+ ContactIdParamsSchema,
13
+ ListCompaniesQuerySchema,
14
+ ListContactsQuerySchema,
15
+ CreateCompanyRequestSchema,
16
+ UpdateCompanyRequestSchema,
17
+ CreateContactRequestSchema,
18
+ UpdateContactRequestSchema,
19
+ AcqCompanyResponseSchema,
20
+ AcqCompanyListResponseSchema,
21
+ AcqContactResponseSchema,
22
+ AcqContactListResponseSchema,
23
+ AcqCompanySchemas,
24
+ AcqContactSchemas,
25
+ DealStageSchema,
26
+ AcqDealTaskKindSchema,
27
+ DealIdParamsSchema,
28
+ DealTaskIdParamsSchema,
29
+ ListDealsQuerySchema,
30
+ ListDealTasksDueQuerySchema,
31
+ CreateDealNoteRequestSchema,
32
+ CreateDealTaskRequestSchema,
33
+ TransitionItemRequestSchema,
34
+ ExecuteActionParamsSchema,
35
+ ExecuteActionRequestSchema,
36
+ DealContactSummarySchema,
37
+ DealListItemSchema,
38
+ DealListResponseSchema,
39
+ DealDetailResponseSchema,
40
+ DealNoteResponseSchema,
41
+ DealNoteListResponseSchema,
42
+ DealTaskResponseSchema,
43
+ DealTaskListResponseSchema,
44
+ DealSchemas,
45
+ ListStatusSchema,
46
+ ScrapingConfigSchema,
47
+ IcpRubricSchema,
48
+ PipelineStageSchema,
49
+ PipelineConfigSchema,
50
+ ListStageCountsSchema,
51
+ ListTelemetrySchema,
52
+ ListIdParamsSchema,
53
+ CreateListRequestSchema,
54
+ UpdateListRequestSchema,
55
+ UpdateListStatusRequestSchema,
56
+ UpdateListConfigRequestSchema,
57
+ AddCompaniesToListRequestSchema,
58
+ RemoveCompaniesFromListRequestSchema,
59
+ AddContactsToListRequestSchema,
60
+ RecordListExecutionRequestSchema,
61
+ AcqListResponseSchema,
62
+ AcqListListResponseSchema,
63
+ ListTelemetryResponseSchema,
64
+ ListTelemetryListResponseSchema,
65
+ ListExecutionSummarySchema,
66
+ ListExecutionsResponseSchema,
67
+ ListStageProgressSchema,
68
+ ListProgressResponseSchema,
69
+ AcqListSchemas,
70
+ AcqSubstrateSchemas,
71
+ AcqArtifactOwnerKindSchema,
72
+ ListArtifactsQuerySchema,
73
+ CreateArtifactRequestSchema,
74
+ AcqArtifactResponseSchema,
75
+ AcqArtifactListResponseSchema,
76
+ ListMembersQuerySchema,
77
+ MemberIdParamsSchema,
78
+ AcqListMemberContactSummarySchema,
79
+ AcqListMemberResponseSchema,
80
+ AcqListMembersResponseSchema,
81
+ ListCompanyIdParamsSchema,
82
+ AcqListCompanyResponseSchema,
83
+ type AcqArtifactOwnerKind,
84
+ type ListArtifactsQuery,
85
+ type CreateArtifactRequest,
86
+ type AcqArtifactResponse,
87
+ type AcqArtifactListResponse,
88
+ type ListMembersQuery,
89
+ type MemberIdParams,
90
+ type AcqListMemberContactSummary,
91
+ type AcqListMemberResponse,
92
+ type AcqListMembersResponse,
93
+ type ListCompanyIdParams,
94
+ type AcqListCompanyResponse,
95
+ type CompanyIdParams,
96
+ type ContactIdParams,
97
+ type ListCompaniesQuery,
98
+ type ListContactsQuery,
99
+ type CreateCompanyRequest,
100
+ type UpdateCompanyRequest,
101
+ type CreateContactRequest,
102
+ type UpdateContactRequest,
103
+ type AcqCompanyResponse,
104
+ type AcqCompanyListResponse,
105
+ type AcqContactResponse,
106
+ type AcqContactListResponse,
107
+ type AcqCompanyStatus,
108
+ type AcqContactStatus,
109
+ type AcqEmailValid,
110
+ type DealIdParams,
111
+ type DealTaskIdParams,
112
+ type ListDealsQuery,
113
+ type ListDealTasksDueQuery,
114
+ type CreateDealNoteRequest,
115
+ type CreateDealTaskRequest,
116
+ type TransitionItemRequest,
117
+ type ExecuteActionParams,
118
+ type ExecuteActionRequest,
119
+ type DealListResponse,
120
+ type DealDetailResponse,
121
+ type DealNoteResponse,
122
+ type DealNoteListResponse,
123
+ type DealTaskResponse,
124
+ type DealTaskListResponse,
125
+ type ListStatus,
126
+ type ScrapingConfig,
127
+ type IcpRubric,
128
+ type PipelineStage,
129
+ type PipelineConfig,
130
+ type ListStageCountsInput,
131
+ type ListTelemetryInput,
132
+ type ListIdParams,
133
+ type CreateListRequest,
134
+ type UpdateListRequest,
135
+ type UpdateListStatusRequest,
136
+ type UpdateListConfigRequest,
137
+ type AddCompaniesToListRequest,
138
+ type RemoveCompaniesFromListRequest,
139
+ type AddContactsToListRequest,
140
+ type RecordListExecutionRequest,
141
+ type AcqListResponse,
142
+ type AcqListListResponse,
143
+ type ListTelemetryResponse,
144
+ type ListTelemetryListResponse,
145
+ type ListExecutionSummaryInput,
146
+ type ListExecutionsResponse,
147
+ type ListStageProgress,
148
+ type ListProgress
149
+ } from './api-schemas'
@@ -0,0 +1,30 @@
1
+ import { z } from 'zod'
2
+ import { ActivityEventSchema, type ActivityEvent } from './activity-events'
3
+
4
+ /**
5
+ * Stateful trait — the (pipeline_key, stage_key, state_key, activity_log) quartet
6
+ * applied to acq_deals (CRM HITL, shipped 2026-04-27) and being generalized to
7
+ * acq_lists / acq_list_members / acq_list_companies via Track B.
8
+ */
9
+ export interface Stateful {
10
+ pipeline_key: string
11
+ stage_key: string
12
+ state_key: string
13
+ activity_log: ActivityEvent[]
14
+ }
15
+
16
+ export const StatefulSchema = z.object({
17
+ pipeline_key: z.string(),
18
+ stage_key: z.string(),
19
+ state_key: z.string(),
20
+ activity_log: z.array(ActivityEventSchema)
21
+ })
22
+
23
+ /** Generic transition shape — concrete per-entity transitionItem implementations satisfy this. */
24
+ export type TransitionItem<T extends Stateful, TEvent extends ActivityEvent> = (
25
+ item: T,
26
+ transition: { stage_key?: string; state_key?: string; event: TEvent }
27
+ ) => T
28
+
29
+ /** Generic action-derivation shape — concrete per-entity deriveActions implementations satisfy this. */
30
+ export type DeriveActions<T extends Stateful, TAction> = (item: T) => TAction[]
@@ -153,24 +153,54 @@ export interface ContactEnrichmentData {
153
153
  // Domain Types (camelCase transformations of database rows)
154
154
  // =============================================================================
155
155
 
156
- /**
157
- * Acquisition list for organizing contacts and companies.
158
- * Transformed from AcqListRow with camelCase properties.
159
- */
156
+ export type ListStatus = 'draft' | 'enriching' | 'launched' | 'closing' | 'archived'
157
+
158
+ export interface ScrapingConfig {
159
+ source?: string
160
+ query?: string
161
+ filters?: Record<string, unknown>
162
+ [key: string]: unknown
163
+ }
164
+
165
+ export interface IcpRubric {
166
+ targetDescription?: string
167
+ minReviewCount?: number
168
+ minRating?: number
169
+ excludeFranchises?: boolean
170
+ customRules?: string
171
+ qualificationRubricKey?: string | null
172
+ [key: string]: unknown
173
+ }
174
+
175
+ export interface PipelineStage {
176
+ key: string
177
+ label?: string
178
+ description?: string
179
+ resourceId?: string
180
+ inputTemplate?: Record<string, unknown>
181
+ enabled?: boolean
182
+ order?: number
183
+ }
184
+
185
+ export interface PipelineConfig {
186
+ stages: PipelineStage[]
187
+ }
188
+
160
189
  export interface AcqList {
161
190
  id: string
162
191
  organizationId: string
163
192
  name: string
164
193
  description: string | null
165
- type: string
166
194
  batchIds: string[]
167
195
  instantlyCampaignId: string | null
168
- status: string
196
+ status: ListStatus
197
+ scrapingConfig: ScrapingConfig
198
+ icp: IcpRubric
199
+ pipelineConfig: PipelineConfig
169
200
  metadata: Record<string, unknown>
170
201
  launchedAt: Date | null
171
202
  completedAt: Date | null
172
203
  createdAt: Date
173
- config: ListConfig
174
204
  }
175
205
 
176
206
  /**
@@ -198,6 +228,12 @@ export interface AcqCompany {
198
228
  batchId: string | null
199
229
  status: 'active' | 'invalid'
200
230
  verticalResearch: string | null
231
+ /** Track A: flat qualification score (null until a scoring rubric is defined). Added by W1 migration. */
232
+ qualificationScore: number | null
233
+ /** Track A: flat qualification signals jsonb preserving the result payload shape. Added by W1 migration. */
234
+ qualificationSignals: Record<string, unknown> | null
235
+ /** Track A: key identifying the rubric used for qualification. Added by W1 migration. */
236
+ qualificationRubricKey: string | null
201
237
  createdAt: Date
202
238
  updatedAt: Date
203
239
  }
@@ -302,76 +338,7 @@ export interface AcqDealTask {
302
338
  createdByUserId: string | null
303
339
  }
304
340
 
305
- // ─── List Config / Progress / Telemetry Types ────────────────────────────────
306
-
307
- /**
308
- * One ordered step in a list's pipeline. Maps to a deployed workflow
309
- * (e.g. 'lgn-03-company-qualification-workflow'). The `inputTemplate`
310
- * is merged with `{ listId }` at run time to form the workflow input.
311
- */
312
- export interface PipelineStep {
313
- /** Stable key, e.g. 'scrape' | 'extract' | 'qualify' | 'discover' | 'verify' | 'personalize'. */
314
- key: string
315
- /** Human label rendered in the UI stepper. */
316
- label: string
317
- /** Deployed workflow resourceId (e.g. 'lgn-03-company-qualification-workflow'). */
318
- resourceId: string
319
- /** Input defaults merged with `{ listId }` at dispatch. */
320
- inputTemplate: Record<string, unknown>
321
- /** Whether the UI shows the Run button. */
322
- enabled: boolean
323
- /** Display order (ascending). */
324
- order: number
325
- }
326
-
327
- export type CompanyListStage = 'populated' | 'extracted' | 'qualified'
328
-
329
- export type ContactListStage = 'discovered' | 'verified' | 'personalized' | 'uploaded'
330
-
331
- /**
332
- * Per-list pipeline configuration stored as jsonb in `acq_lists.config`.
333
- *
334
- * `qualification` is the only required subtree. Every other subtree is optional
335
- * and inherits global defaults when omitted: workflows resolve values as
336
- * `list.config.foo ?? globalDefaults.foo`. Seeded rows from
337
- * `20260413000100_backfill_list_configs.sql` only populate `qualification`
338
- * and `scraping`; the rest was intentionally omitted.
339
- */
340
- export interface ListConfig {
341
- qualification: {
342
- /** One-line description of the target vertical/segment. */
343
- targetDescription: string
344
- /** Minimum Google review count to qualify. */
345
- minReviewCount: number
346
- /** Minimum Google star rating to qualify (e.g. 3.0). */
347
- minRating: number
348
- /** Whether to exclude franchises/chains during qualification. */
349
- excludeFranchises: boolean
350
- /** Free-form LLM rules layered on top of the structured criteria. */
351
- customRules: string
352
- }
353
- enrichment?: {
354
- emailDiscovery?: {
355
- primary: 'tomba' | 'anymailfinder'
356
- credentialName?: string
357
- }
358
- emailVerification?: {
359
- provider: 'millionverifier'
360
- threshold?: 'ok' | 'ok+catch_all'
361
- }
362
- }
363
- personalization?: {
364
- industryContext?: string
365
- /** Email body template with tags like {{opening_line}} / {{category_pain}}. */
366
- emailBody?: string
367
- creativeDirection?: string
368
- /** Contradiction-prevention rules layered into the personalization prompt. */
369
- exclusionRules?: string[]
370
- }
371
- pipeline?: {
372
- steps: PipelineStep[]
373
- }
374
- }
341
+ // ─── Progress / Telemetry Types ──────────────────────────────────────────────
375
342
 
376
343
  /**
377
344
  * Live-scan aggregate telemetry for a single list, computed on demand from