@sellable/mcp 0.1.151 → 0.1.153
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/README.md +4 -3
- package/agents/post-find-leads-filter-scout.md +5 -4
- package/agents/post-find-leads-message-scout.md +15 -14
- package/agents/source-scout-linkedin-engagement.md +6 -5
- package/agents/source-scout-prospeo-contact.md +4 -4
- package/agents/source-scout-sales-nav.md +4 -4
- package/dist/index-dev.js +0 -0
- package/dist/index.js +0 -0
- package/dist/tools/cells.js +1 -1
- package/dist/tools/leads.d.ts +37 -3
- package/dist/tools/leads.js +85 -77
- package/dist/tools/prompts.js +9 -9
- package/dist/tools/readiness.d.ts +7 -1
- package/dist/tools/readiness.js +10 -17
- package/dist/tools/registry.d.ts +17 -0
- package/dist/tools/rubrics.js +23 -20
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +59 -56
- package/skills/create-campaign-v2/SKILL.md +44 -42
- package/skills/create-campaign-v2/SOUL.md +16 -13
- package/skills/create-campaign-v2/core/auto-execute.README.md +16 -17
- package/skills/create-campaign-v2/core/auto-execute.yaml +8 -7
- package/skills/create-campaign-v2/core/flow.v2.json +81 -149
- package/skills/create-campaign-v2/core/policy.md +13 -12
- package/skills/create-campaign-v2/references/approval-gate-framing.md +4 -3
- package/skills/create-campaign-v2/references/filter-leads.md +5 -4
- package/skills/create-campaign-v2/references/lead-validation-preview.md +2 -2
- package/skills/create-campaign-v2/references/sample-validation-loop.md +32 -27
- package/skills/create-campaign-v2/references/step-13-import-leads.md +44 -33
- package/skills/create-campaign-v2/references/watch-guide-narration.md +27 -28
- package/skills/create-campaign-v2-tail/SKILL.md +44 -44
- package/skills/create-rubric/SKILL.md +5 -5
- package/skills/find-leads/SKILL.md +2 -2
- package/skills/generate-messages/SKILL.md +2 -1
- package/skills/providers/prospeo.md +3 -3
- package/skills/providers/sales-nav.md +7 -7
- package/skills/providers/signal-discovery.md +47 -23
package/dist/tools/registry.d.ts
CHANGED
|
@@ -1391,6 +1391,7 @@ export declare const allTools: ({
|
|
|
1391
1391
|
campaignName?: undefined;
|
|
1392
1392
|
keepInSync?: undefined;
|
|
1393
1393
|
jobId?: undefined;
|
|
1394
|
+
reviewBatchLimit?: undefined;
|
|
1394
1395
|
selections?: undefined;
|
|
1395
1396
|
selectionMode?: undefined;
|
|
1396
1397
|
};
|
|
@@ -1566,6 +1567,7 @@ export declare const allTools: ({
|
|
|
1566
1567
|
campaignName?: undefined;
|
|
1567
1568
|
keepInSync?: undefined;
|
|
1568
1569
|
jobId?: undefined;
|
|
1570
|
+
reviewBatchLimit?: undefined;
|
|
1569
1571
|
selections?: undefined;
|
|
1570
1572
|
selectionMode?: undefined;
|
|
1571
1573
|
};
|
|
@@ -1640,6 +1642,7 @@ export declare const allTools: ({
|
|
|
1640
1642
|
campaignName?: undefined;
|
|
1641
1643
|
keepInSync?: undefined;
|
|
1642
1644
|
jobId?: undefined;
|
|
1645
|
+
reviewBatchLimit?: undefined;
|
|
1643
1646
|
selections?: undefined;
|
|
1644
1647
|
selectionMode?: undefined;
|
|
1645
1648
|
};
|
|
@@ -1786,6 +1789,7 @@ export declare const allTools: ({
|
|
|
1786
1789
|
campaignName?: undefined;
|
|
1787
1790
|
keepInSync?: undefined;
|
|
1788
1791
|
jobId?: undefined;
|
|
1792
|
+
reviewBatchLimit?: undefined;
|
|
1789
1793
|
selections?: undefined;
|
|
1790
1794
|
selectionMode?: undefined;
|
|
1791
1795
|
};
|
|
@@ -1874,6 +1878,7 @@ export declare const allTools: ({
|
|
|
1874
1878
|
campaignName?: undefined;
|
|
1875
1879
|
keepInSync?: undefined;
|
|
1876
1880
|
jobId?: undefined;
|
|
1881
|
+
reviewBatchLimit?: undefined;
|
|
1877
1882
|
selections?: undefined;
|
|
1878
1883
|
selectionMode?: undefined;
|
|
1879
1884
|
};
|
|
@@ -1971,6 +1976,7 @@ export declare const allTools: ({
|
|
|
1971
1976
|
campaignName?: undefined;
|
|
1972
1977
|
keepInSync?: undefined;
|
|
1973
1978
|
jobId?: undefined;
|
|
1979
|
+
reviewBatchLimit?: undefined;
|
|
1974
1980
|
selections?: undefined;
|
|
1975
1981
|
selectionMode?: undefined;
|
|
1976
1982
|
};
|
|
@@ -2050,6 +2056,7 @@ export declare const allTools: ({
|
|
|
2050
2056
|
campaignName?: undefined;
|
|
2051
2057
|
keepInSync?: undefined;
|
|
2052
2058
|
jobId?: undefined;
|
|
2059
|
+
reviewBatchLimit?: undefined;
|
|
2053
2060
|
selections?: undefined;
|
|
2054
2061
|
selectionMode?: undefined;
|
|
2055
2062
|
};
|
|
@@ -2668,6 +2675,7 @@ export declare const allTools: ({
|
|
|
2668
2675
|
campaignName?: undefined;
|
|
2669
2676
|
keepInSync?: undefined;
|
|
2670
2677
|
jobId?: undefined;
|
|
2678
|
+
reviewBatchLimit?: undefined;
|
|
2671
2679
|
selections?: undefined;
|
|
2672
2680
|
selectionMode?: undefined;
|
|
2673
2681
|
};
|
|
@@ -2799,6 +2807,7 @@ export declare const allTools: ({
|
|
|
2799
2807
|
campaignName?: undefined;
|
|
2800
2808
|
keepInSync?: undefined;
|
|
2801
2809
|
jobId?: undefined;
|
|
2810
|
+
reviewBatchLimit?: undefined;
|
|
2802
2811
|
selections?: undefined;
|
|
2803
2812
|
selectionMode?: undefined;
|
|
2804
2813
|
};
|
|
@@ -2918,6 +2927,7 @@ export declare const allTools: ({
|
|
|
2918
2927
|
campaignName?: undefined;
|
|
2919
2928
|
keepInSync?: undefined;
|
|
2920
2929
|
jobId?: undefined;
|
|
2930
|
+
reviewBatchLimit?: undefined;
|
|
2921
2931
|
selections?: undefined;
|
|
2922
2932
|
selectionMode?: undefined;
|
|
2923
2933
|
};
|
|
@@ -2995,6 +3005,7 @@ export declare const allTools: ({
|
|
|
2995
3005
|
campaignName?: undefined;
|
|
2996
3006
|
keepInSync?: undefined;
|
|
2997
3007
|
jobId?: undefined;
|
|
3008
|
+
reviewBatchLimit?: undefined;
|
|
2998
3009
|
selections?: undefined;
|
|
2999
3010
|
selectionMode?: undefined;
|
|
3000
3011
|
};
|
|
@@ -3034,6 +3045,10 @@ export declare const allTools: ({
|
|
|
3034
3045
|
type: string;
|
|
3035
3046
|
description: string;
|
|
3036
3047
|
};
|
|
3048
|
+
reviewBatchLimit: {
|
|
3049
|
+
type: string;
|
|
3050
|
+
description: string;
|
|
3051
|
+
};
|
|
3037
3052
|
confirmed: {
|
|
3038
3053
|
type: string;
|
|
3039
3054
|
description: string;
|
|
@@ -3192,6 +3207,7 @@ export declare const allTools: ({
|
|
|
3192
3207
|
campaignName?: undefined;
|
|
3193
3208
|
keepInSync?: undefined;
|
|
3194
3209
|
jobId?: undefined;
|
|
3210
|
+
reviewBatchLimit?: undefined;
|
|
3195
3211
|
};
|
|
3196
3212
|
required: string[];
|
|
3197
3213
|
};
|
|
@@ -3271,6 +3287,7 @@ export declare const allTools: ({
|
|
|
3271
3287
|
campaignName?: undefined;
|
|
3272
3288
|
keepInSync?: undefined;
|
|
3273
3289
|
jobId?: undefined;
|
|
3290
|
+
reviewBatchLimit?: undefined;
|
|
3274
3291
|
selections?: undefined;
|
|
3275
3292
|
selectionMode?: undefined;
|
|
3276
3293
|
};
|
package/dist/tools/rubrics.js
CHANGED
|
@@ -95,16 +95,16 @@ async function fetchCampaignOffer(campaignOfferId) {
|
|
|
95
95
|
leadScoringRubrics: v3.rubrics,
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
|
-
const
|
|
98
|
+
const filterRulesSavedForReviewWatchNarration = {
|
|
99
99
|
stage: "fit-message",
|
|
100
|
-
headline: "Filter rules saved",
|
|
101
|
-
visibleState: "The browser is
|
|
102
|
-
agentIntent: "Codex is
|
|
103
|
-
nextAction: "
|
|
100
|
+
headline: "Filter rules saved for review",
|
|
101
|
+
visibleState: "The browser is showing Filter Rules with the saved criteria.",
|
|
102
|
+
agentIntent: "Codex is waiting for filter approval before the review batch is enriched or scored.",
|
|
103
|
+
nextAction: "Approve or revise the filters",
|
|
104
104
|
progressLabel: "Fit + message",
|
|
105
|
-
safety: "
|
|
105
|
+
safety: "Saved rules are ready to review; downstream row processing remains gated.",
|
|
106
106
|
};
|
|
107
|
-
function
|
|
107
|
+
function shouldKeepFilterRulesVisible(campaign) {
|
|
108
108
|
const currentStep = campaign.currentStep;
|
|
109
109
|
if (!currentStep)
|
|
110
110
|
return true;
|
|
@@ -116,16 +116,15 @@ function shouldMoveToFilterLeads(campaign) {
|
|
|
116
116
|
"filter-choice",
|
|
117
117
|
"create-icp-rubric",
|
|
118
118
|
"filter-rules",
|
|
119
|
-
"apply-icp-rubric",
|
|
120
119
|
].includes(currentStep);
|
|
121
120
|
}
|
|
122
121
|
function buildEnableIcpFiltersPayload(campaign) {
|
|
123
122
|
const payload = {
|
|
124
123
|
enableICPFilters: true,
|
|
125
124
|
};
|
|
126
|
-
if (
|
|
127
|
-
payload.currentStep = "
|
|
128
|
-
payload.watchNarration =
|
|
125
|
+
if (shouldKeepFilterRulesVisible(campaign)) {
|
|
126
|
+
payload.currentStep = "create-icp-rubric";
|
|
127
|
+
payload.watchNarration = filterRulesSavedForReviewWatchNarration;
|
|
129
128
|
}
|
|
130
129
|
return payload;
|
|
131
130
|
}
|
|
@@ -245,7 +244,7 @@ export const rubricToolDefinitions = [
|
|
|
245
244
|
},
|
|
246
245
|
{
|
|
247
246
|
name: "save_rubrics",
|
|
248
|
-
description: "Persist rubric criteria to the campaign. Pass leadScoringRubrics directly to save without drafting. Saving active rubrics enables ICP filtering and
|
|
247
|
+
description: "Persist rubric criteria to the campaign. Pass leadScoringRubrics directly to save without drafting. Saving active rubrics enables ICP filtering and keeps the watched client on Filter Rules for user approval; it does not move to Filter Leads or run filtering by itself.",
|
|
249
248
|
inputSchema: {
|
|
250
249
|
type: "object",
|
|
251
250
|
properties: {
|
|
@@ -580,12 +579,16 @@ export async function saveRubrics(input) {
|
|
|
580
579
|
// cascade blocked.
|
|
581
580
|
let enableICPFiltersSet = false;
|
|
582
581
|
let currentStepSet = false;
|
|
582
|
+
let savedCurrentStep = null;
|
|
583
583
|
try {
|
|
584
584
|
const api = getApi();
|
|
585
585
|
const payload = buildEnableIcpFiltersPayload(campaign);
|
|
586
586
|
await api.put(`/api/v2/campaign-offers/${input.campaignOfferId}`, payload);
|
|
587
587
|
enableICPFiltersSet = true;
|
|
588
|
-
|
|
588
|
+
if (typeof payload.currentStep === "string") {
|
|
589
|
+
savedCurrentStep = payload.currentStep;
|
|
590
|
+
currentStepSet = true;
|
|
591
|
+
}
|
|
589
592
|
}
|
|
590
593
|
catch (error) {
|
|
591
594
|
// Non-fatal: the rubric save already succeeded. Retry the minimum
|
|
@@ -604,17 +607,17 @@ export async function saveRubrics(input) {
|
|
|
604
607
|
}
|
|
605
608
|
return {
|
|
606
609
|
success: true,
|
|
607
|
-
message:
|
|
608
|
-
? `Saved ${normalizedDraft.length} rubric criteria, ICP filtering is ON, and the campaign is
|
|
609
|
-
:
|
|
610
|
+
message: savedCurrentStep === "create-icp-rubric"
|
|
611
|
+
? `Saved ${normalizedDraft.length} rubric criteria, ICP filtering is ON, and the campaign is waiting for filter approval.`
|
|
612
|
+
: currentStepSet
|
|
610
613
|
? `Saved ${normalizedDraft.length} rubric criteria and ICP filtering is ON.`
|
|
611
|
-
:
|
|
614
|
+
: enableICPFiltersSet || campaign.enableICPFilters === true
|
|
615
|
+
? `Saved ${normalizedDraft.length} rubric criteria and ICP filtering is ON.`
|
|
616
|
+
: `Saved ${normalizedDraft.length} rubric criteria to the campaign. WARNING: could not auto-enable ICP filtering — call update_campaign({ campaignId, enableICPFilters: true }) to activate rubric-based filtering.`,
|
|
612
617
|
criteriaCount: normalizedDraft.length,
|
|
613
618
|
deletedCount: deletedRubricIds.length,
|
|
614
619
|
enableICPFiltersSet,
|
|
615
|
-
currentStep:
|
|
616
|
-
? "apply-icp-rubric"
|
|
617
|
-
: (campaign.currentStep ?? null),
|
|
620
|
+
currentStep: savedCurrentStep ?? campaign.currentStep ?? null,
|
|
618
621
|
currentStepSet,
|
|
619
622
|
rubrics: result?.rubrics ?? normalizedDraft,
|
|
620
623
|
activeRubrics: result?.rubrics ?? normalizedDraft,
|
package/package.json
CHANGED
|
@@ -72,10 +72,10 @@ not create, link, or surface local draft files unless the user explicitly asks
|
|
|
72
72
|
for them. Resume, gating, and handoff read campaign state first. The
|
|
73
73
|
watchable campaign exists after the short brief; lead import is bounded to the
|
|
74
74
|
first review batch. After that, the user chooses whether to use filters or skip.
|
|
75
|
-
When filters are chosen, save rubrics,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
When filters are chosen, save rubrics, get filter approval, then wait for
|
|
76
|
+
message-template approval before enrichment/filtering or Generate Message cells.
|
|
77
|
+
Use Template is the default message path; AI Generated is only an explicit
|
|
78
|
+
opt-out.
|
|
79
79
|
|
|
80
80
|
## Opening Turn Contract
|
|
81
81
|
|
|
@@ -124,9 +124,10 @@ data, compare sources by source volume, sampled ICP fit, activity/warmth
|
|
|
124
124
|
signals, cleanup risk, and confidence basis. If a user asks for a forecast,
|
|
125
125
|
label it explicitly as not estimated from this run.
|
|
126
126
|
|
|
127
|
-
Before any provider prompt, search, source scout, or signal-discovery call,
|
|
128
|
-
|
|
129
|
-
authorizes scouting/search only. The gate
|
|
127
|
+
Before any provider prompt, search, source scout, or signal-discovery call, show
|
|
128
|
+
one source-plan gate and ask for approval. The plan must be visible before the
|
|
129
|
+
question, and this first approval authorizes scouting/search only. The gate
|
|
130
|
+
should say:
|
|
130
131
|
|
|
131
132
|
- given this campaign, the viable source options
|
|
132
133
|
- the recommended first lane
|
|
@@ -143,6 +144,10 @@ why. Do not call `search_signals`, `search_sales_nav`, `search_prospeo`,
|
|
|
143
144
|
`fetch_post_engagers`, or provider-scoped subagents until the user approves this
|
|
144
145
|
source plan or explicitly chooses a different source.
|
|
145
146
|
|
|
147
|
+
If the user already answered a provider approval such as "Approve Prospeo plan",
|
|
148
|
+
that answer satisfies the source-plan gate. Persist the approved provider and
|
|
149
|
+
run the scouting/search next; do not ask a second source-plan approval question.
|
|
150
|
+
|
|
146
151
|
For hiring-led campaigns, do not default to Sales Nav just because the target is
|
|
147
152
|
a role search. Prospeo is the primary lane when the brief asks for companies
|
|
148
153
|
actively hiring specific roles, open-role signals, account/contact coverage, or
|
|
@@ -153,41 +158,42 @@ are likely. Sales Nav is useful for recent LinkedIn activity, role/title
|
|
|
153
158
|
precision, and referral paths, but it does not provide hiring-by-role filters;
|
|
154
159
|
say that distinction plainly in the source-plan gate.
|
|
155
160
|
|
|
156
|
-
After scouting, ask for a second approval on the concrete source action. For
|
|
157
|
-
Signal Discovery, name how many selected posts will be scraped, the target
|
|
158
|
-
engager/source-candidate volume, and the
|
|
159
|
-
Nav or Prospeo, name the specific approved import lane and source lead count.
|
|
161
|
+
After scouting, ask for a second approval on the concrete source action. For
|
|
162
|
+
Signal Discovery, name how many selected posts will be scraped, the target
|
|
163
|
+
engager/source-candidate volume, and the 15-row review/process sample size. For Sales
|
|
164
|
+
Nav or Prospeo, name the specific approved import lane and source lead count.
|
|
165
|
+
|
|
160
166
|
Do not call `import_leads` or `confirm_lead_list` until this second approval is
|
|
161
167
|
granted.
|
|
162
168
|
|
|
163
|
-
For Sales Nav and Prospeo, the second gate approves materializing the source
|
|
164
|
-
lead list, not importing only the review batch. Use the first-page/sample review
|
|
165
|
-
to calculate projected good fits: sampled fit rate after conservative cleanup,
|
|
166
|
-
raw pool size, source target, and expected good-fit count. If the projected
|
|
167
|
-
good-fit pool is below the campaign target
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
169
|
+
For Sales Nav and Prospeo, the second gate approves materializing the source
|
|
170
|
+
lead list, not importing only the review batch. Use the first-page/sample review
|
|
171
|
+
to calculate projected good fits: sampled fit rate after conservative cleanup,
|
|
172
|
+
raw pool size, source target, and expected good-fit count. If the projected
|
|
173
|
+
good-fit pool is below the campaign target, keep refining/broadening filters
|
|
174
|
+
before asking for import approval. Once it clears target, approve `import_leads`
|
|
175
|
+
with a source-list `targetLeadCount` around 1,000 by default (provider cap is
|
|
176
|
+
internal when the raw pool is larger). Only after the source list is ready
|
|
177
|
+
should `confirm_lead_list({ reviewBatchLimit: 15 })` copy confirmed rows into
|
|
178
|
+
the campaign table and return the first 15 review/process rows.
|
|
173
179
|
|
|
174
180
|
For Signal Discovery, the customer-facing approval card must use the exact
|
|
175
181
|
action shape "Approve scraping N Signal Discovery posts?" and the chat summary
|
|
176
182
|
should be a compact `## Source Recommendation` block with:
|
|
177
183
|
|
|
178
|
-
-
|
|
179
|
-
- source-candidate plan: about 1,
|
|
180
|
-
|
|
184
|
+
- goal: about 300 good-fit prospects after cleanup, enrichment, and filters
|
|
185
|
+
- source-candidate plan: about 1,500 raw engagers using a 20% working fit-rate
|
|
186
|
+
assumption unless sampled data supports a different number
|
|
181
187
|
- planning floor: continue with Signal Discovery only when sampled/projected
|
|
182
188
|
fit is at least 10% after cleanup; below that, move to Sales Nav recent
|
|
183
189
|
activity instead of scraping noisy engagers
|
|
184
|
-
- review checkpoint: after the source list exists,
|
|
185
|
-
|
|
190
|
+
- review checkpoint: after the source list exists, copy confirmed source rows
|
|
191
|
+
into the campaign and process only the first 15 for fit and message review
|
|
186
192
|
- a selected-post table with post author/topic, why it fits, and visible
|
|
187
193
|
engagement
|
|
188
194
|
- total visible pool and estimated good-fit pool
|
|
189
|
-
- first pass: build the source list
|
|
190
|
-
then
|
|
195
|
+
- first pass: build the source list, copy all confirmed source rows into the
|
|
196
|
+
campaign, then process only the first 15 rows before scaling
|
|
191
197
|
- fallback: switch to Sales Nav recent activity if sampled/projected fit falls
|
|
192
198
|
below 10%, or if the review batch is vendor-heavy, agency-heavy, or off-ICP
|
|
193
199
|
|
|
@@ -217,17 +223,19 @@ which posts are being sampled in the watched app. The watch guide should say
|
|
|
217
223
|
that we are pulling sample engagers from these posts to confirm the ICP is
|
|
218
224
|
actually engaging and the source is viable.
|
|
219
225
|
|
|
220
|
-
After
|
|
226
|
+
After confirmed source rows exist in the campaign table, use the same registry pattern for
|
|
227
|
+
|
|
221
228
|
post-lead work, but do not load that registry or any deep filter/message prompt
|
|
222
229
|
before the filter-choice question. After `confirm_lead_list`, ask add filters
|
|
223
230
|
vs skip filters immediately. Once the user answers, launch the message scout
|
|
224
231
|
from the same campaign/table basis. If the user chooses filters, also launch the
|
|
225
|
-
filter-leads scout, move to Filter Rules, save rubrics, then
|
|
226
|
-
|
|
227
|
-
filters, move to Messages/message
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
232
|
+
filter-leads scout, move to Filter Rules, save rubrics, then ask for filter
|
|
233
|
+
approval. After approval, keep the browser on Filter Leads while the message
|
|
234
|
+
recommendation is reviewed. If the user skips filters, move to Messages/message
|
|
235
|
+
review. Enrichment/filtering and Generate Message cells wait for message
|
|
236
|
+
approval. AI Generated is an explicit opt-out from the template path. If the
|
|
237
|
+
post-lead agents are absent, the main thread still orchestrates the same
|
|
238
|
+
branches from compact MCP context.
|
|
231
239
|
|
|
232
240
|
Use rendered Markdown for user review surfaces, not fenced code blocks. Keep
|
|
233
241
|
lines short, use indexed section labels and bullets, and translate internal
|
|
@@ -643,29 +651,23 @@ updates.
|
|
|
643
651
|
until `hasMore=false`. Message review requires Message Draft Builder output:
|
|
644
652
|
do not draft from a checklist, local markdown artifact, or parent-thread
|
|
645
653
|
intuition. Use campaign state, campaign brief content, selected source state, and
|
|
646
|
-
|
|
654
|
+
first review/process sample rows as the source of truth; do not read stale local
|
|
647
655
|
markdown such as `message-validation.md`, inspect the database directly, or
|
|
648
656
|
synthesize local validation artifacts from general knowledge.
|
|
649
657
|
5. Create the campaign shell early with the v1 brief so the user can open the
|
|
650
|
-
watch link and see useful setup state immediately.
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
are approved
|
|
655
|
-
is synced into the campaign brief. When filters are approved, immediately
|
|
658
|
+
watch link and see useful setup state immediately. Materialize the approved
|
|
659
|
+
source list, copy confirmed rows into the campaign, and process only the
|
|
660
|
+
first 15 review rows after the source is attached to the campaign; do not
|
|
661
|
+
queue workflow cells, attach a sequence, or start until saved filters and the
|
|
662
|
+
message template/token rules are approved. When filters are chosen, immediately
|
|
656
663
|
call `mcp__sellable__update_campaign({ campaignId, enableICPFilters: true, currentStep: "create-icp-rubric", watchNarration })`
|
|
657
664
|
so the watched app moves to Filter Rules while rubrics are drafted/saved.
|
|
658
|
-
After rubrics save,
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
Messages
|
|
663
|
-
|
|
664
|
-
`enrichCellId` cells to kick off enrichment/filtering. Move to Messages only
|
|
665
|
-
after at least one review row passes and Generate Message cells are running or
|
|
666
|
-
ready.
|
|
667
|
-
Product Generate Message cells must not run before that template/token
|
|
668
|
-
approval.
|
|
665
|
+
After rubrics save, keep Filter Rules visible for approval; after approval,
|
|
666
|
+
move to Filter Leads and wait there for the background message recommendation.
|
|
667
|
+
If filters are skipped, move to Messages/message review. Queue the bounded
|
|
668
|
+
review-batch `enrichCellId` cells only after message approval. Move to
|
|
669
|
+
Messages only after at least one review row passes and one generated message
|
|
670
|
+
is ready.
|
|
669
671
|
Do not ask the user to approve the brief before shell creation unless they
|
|
670
672
|
explicitly requested a no-write draft; the shell itself is the review surface.
|
|
671
673
|
6. The main thread owns watch navigation. Call
|
|
@@ -673,9 +675,10 @@ updates.
|
|
|
673
675
|
visible work so the user can watch progress in the app: `create-offer` for
|
|
674
676
|
the brief, `pick-provider` or the selected provider step while sourcing,
|
|
675
677
|
`filter-choice` after the review batch, `create-icp-rubric` as soon
|
|
676
|
-
as filters are
|
|
677
|
-
|
|
678
|
-
|
|
678
|
+
as filters are chosen and while saved filters await approval,
|
|
679
|
+
`apply-icp-rubric` after filter approval and message approval while bounded
|
|
680
|
+
enrichment/filter scoring runs, `validate-sample` only as a recovery/legacy
|
|
681
|
+
observation state,
|
|
679
682
|
`auto-execute-messaging` after at least one row passes and review-batch
|
|
680
683
|
messages are being generated or reviewed, `awaiting-user-greenlight` only
|
|
681
684
|
after generated review-batch messages are approved, `settings` for sender
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: create-campaign-v2
|
|
3
|
-
description: Execute the compact JSON-gated shell-first campaign flow: resolve campaign identity, create a watchable CampaignOffer shell with the brief, attach and approve the source,
|
|
3
|
+
description: Execute the compact JSON-gated shell-first campaign flow: resolve campaign identity, create a watchable CampaignOffer shell with the brief, attach and approve the source, copy the confirmed source list into the campaign, process the first 15 review rows, persist rubrics and approved message template, validate the first passing generated message, then hand off to Settings, sequence, and start.
|
|
4
4
|
visibility: internal
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -40,19 +40,17 @@ for debug output.
|
|
|
40
40
|
4. Create the watchable campaign shell with `create_campaign` and the v1 brief.
|
|
41
41
|
5. Surface the direct watch link.
|
|
42
42
|
6. Choose and approve the lead source.
|
|
43
|
-
7.
|
|
43
|
+
7. Materialize the approved source list, confirm/copy it into the campaign, and
|
|
44
|
+
use only the first 15 rows as the initial review/process sample.
|
|
44
45
|
8. Ask whether to use filters or skip them.
|
|
45
|
-
9. Persist lead rubrics when filters are enabled
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
11. Review and approve/revise the message.
|
|
49
|
-
12. Sync the approved template into the
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
message is ready for review. Do not wait for a stronger sample once that
|
|
54
|
-
first passing message exists; review it, then hand off to Settings, sender,
|
|
55
|
-
sequence, and explicit launch greenlight.
|
|
46
|
+
9. Persist lead rubrics when filters are enabled, then ask approval while the
|
|
47
|
+
app remains on Filter Rules.
|
|
48
|
+
10. Move to Filter Leads only after saved filters are approved.
|
|
49
|
+
11. Review and approve/revise the message template.
|
|
50
|
+
12. Sync the approved template into the brief, then queue bounded
|
|
51
|
+
enrichment/filtering.
|
|
52
|
+
13. Move to Messages after one row passes and one generated message is ready;
|
|
53
|
+
review it, then hand off to Settings, sender, sequence, and launch.
|
|
56
54
|
|
|
57
55
|
There is no normal approval-packet, commit-gate, atomic-mint, or local
|
|
58
56
|
artifact-validation step. Those belong only to legacy validation/rehearsal
|
|
@@ -136,9 +134,9 @@ can be a conversation-signal check if relevant hiring posts are likely, and
|
|
|
136
134
|
Sales Nav is a LinkedIn activity/referral fallback rather than the main hiring
|
|
137
135
|
filter.
|
|
138
136
|
|
|
139
|
-
Before any provider prompt, search, source scout, or signal-discovery call,
|
|
140
|
-
|
|
141
|
-
authorizes source scouting/search only
|
|
137
|
+
Before any provider prompt, search, source scout, or signal-discovery call, show
|
|
138
|
+
one source-plan gate and ask for approval. The gate must include the plan before
|
|
139
|
+
the question, and this first approval authorizes source scouting/search only:
|
|
142
140
|
|
|
143
141
|
- given this campaign, the viable source options
|
|
144
142
|
- the recommended first lane
|
|
@@ -151,7 +149,9 @@ Do not surface blanket source heuristics as product copy. Make the recommendatio
|
|
|
151
149
|
specific to the campaign. If Signal Discovery is recommended, name the exact
|
|
152
150
|
post themes you will search. If the campaign looks unlikely to have relevant
|
|
153
151
|
public conversations, recommend the specific Sales Nav or Prospeo lane instead
|
|
154
|
-
and say why.
|
|
152
|
+
and say why. An approval like "Approve Prospeo plan" satisfies this gate; persist
|
|
153
|
+
the provider and search next. Do not ask a second source-plan question. Do not
|
|
154
|
+
call `search_signals`, `search_sales_nav`, `search_prospeo`,
|
|
155
155
|
`fetch_post_engagers`, or provider-scoped subagents until the user approves this
|
|
156
156
|
source plan or explicitly chooses a different source.
|
|
157
157
|
|
|
@@ -176,17 +176,17 @@ name the specific search/import lane and source lead count. Do not call
|
|
|
176
176
|
`import_leads` or `confirm_lead_list` until this second source-action approval
|
|
177
177
|
is granted.
|
|
178
178
|
|
|
179
|
-
For Sales Nav and Prospeo, do not ask to import only the
|
|
179
|
+
For Sales Nav and Prospeo, do not ask to import only the 15-row review sample at
|
|
180
180
|
the source-action gate. First-page samples are for source math: compute sampled
|
|
181
181
|
fit after conservative cleanup, project how many good-fit prospects the raw
|
|
182
182
|
pool can yield, and keep refining filters while the projected good-fit pool is
|
|
183
|
-
below the campaign target
|
|
184
|
-
campaign/source defaults say otherwise). Once the lane clears the target, ask
|
|
183
|
+
below the campaign target. Once the lane clears the target, ask
|
|
185
184
|
approval to materialize the source list with
|
|
186
|
-
`targetLeadCount
|
|
187
|
-
|
|
188
|
-
`confirm_lead_list
|
|
189
|
-
table for fit and
|
|
185
|
+
`targetLeadCount` around 1,000 source contacts by default (use the provider cap
|
|
186
|
+
internally when the raw pool is larger). After that source list is ready,
|
|
187
|
+
`confirm_lead_list({ reviewBatchLimit: 15 })` copies confirmed source rows into
|
|
188
|
+
the campaign table and returns the first 15 review/process row ids for fit and
|
|
189
|
+
message review.
|
|
190
190
|
|
|
191
191
|
After the user approves this concrete source-action gate, do not show the
|
|
192
192
|
Source Recommendation again and do not ask another source approval question.
|
|
@@ -205,10 +205,11 @@ selected posts exist:
|
|
|
205
205
|
|
|
206
206
|
Use Signal Discovery first.
|
|
207
207
|
|
|
208
|
-
**
|
|
209
|
-
**
|
|
208
|
+
**Goal:** ~300 good-fit prospects after cleanup, enrichment, and filters<br>
|
|
209
|
+
**Working assumption:** ~20% of raw post engagers become good-fit prospects<br>
|
|
210
|
+
**Engagers needed:** ~1,500 raw engagers<br>
|
|
210
211
|
**Planning floor:** continue only when sampled/projected fit is at least 10% after cleanup; below that, switch to Sales Nav recent activity<br>
|
|
211
|
-
**Review checkpoint:** after the source list exists,
|
|
212
|
+
**Review checkpoint:** after the source list exists, copy the entire confirmed source list into the campaign and process only the first 15 rows for fit and message review<br>
|
|
212
213
|
|
|
213
214
|
### Selected posts
|
|
214
215
|
|
|
@@ -219,19 +220,19 @@ Use Signal Discovery first.
|
|
|
219
220
|
| Divyanshi Sharma | LinkedIn lead-gen system built with Claude Code | ~508 |
|
|
220
221
|
|
|
221
222
|
**Total visible pool:** ~2,813 engagers<br>
|
|
222
|
-
**Estimated good-fit pool at
|
|
223
|
+
**Estimated good-fit pool at 20%:** ~560 prospects before dedupe/risk cleanup
|
|
223
224
|
|
|
224
225
|
### Recommendation
|
|
225
226
|
|
|
226
227
|
Approve scraping these 3 posts.
|
|
227
228
|
|
|
228
|
-
This gives enough volume to
|
|
229
|
+
This gives enough volume to target ~300 good-fit prospects after cleanup, while
|
|
229
230
|
keeping the source tied to people already engaging with Claude Code outbound /
|
|
230
231
|
AI-native sales workflows.
|
|
231
232
|
|
|
232
|
-
**First pass:** build the source list
|
|
233
|
-
then
|
|
234
|
-
|
|
233
|
+
**First pass:** build the source list, copy all confirmed source rows into the
|
|
234
|
+
campaign, then process only the first 15 rows so we can inspect quality before
|
|
235
|
+
scaling.
|
|
235
236
|
|
|
236
237
|
**Fallback:** if sampled/projected fit falls below 10%, or if the review batch
|
|
237
238
|
is too vendor-heavy, agency-heavy, or off-ICP, switch to Sales Nav recent
|
|
@@ -245,7 +246,7 @@ authorizes. For Sales Nav/Prospeo it must also show source export math:
|
|
|
245
246
|
`rawResultCount`, `sampledFitRate`, conservative projected fit rate,
|
|
246
247
|
`targetLeadCount` for the source list, and projected good-fit count from that
|
|
247
248
|
export. If projected good-fit count is below target, the recommendation is to
|
|
248
|
-
refine or broaden filters, not to
|
|
249
|
+
refine or broaden filters, not to run a 15-row review sample.
|
|
249
250
|
|
|
250
251
|
Supplied profile CSVs, company/domain CSVs, pasted domains, and existing
|
|
251
252
|
Sellable lead lists are supported, but keep provider mechanics out of the first
|
|
@@ -253,7 +254,7 @@ customer-facing source-choice labels.
|
|
|
253
254
|
|
|
254
255
|
## Post-Lead Workstreams
|
|
255
256
|
|
|
256
|
-
After `confirm_lead_list`
|
|
257
|
+
After `confirm_lead_list` copies a non-empty confirmed source into the campaign and
|
|
257
258
|
`get_rows_minimal({ tableId: workflowTableId })` proves rows exist, ask the
|
|
258
259
|
filter-choice question immediately. Do not call
|
|
259
260
|
`get_post_find_leads_scout_registry`, load filter/message subskill prompts, or
|
|
@@ -271,11 +272,12 @@ are optional only.
|
|
|
271
272
|
When the user chooses filters, immediately call
|
|
272
273
|
`update_campaign({ campaignId, enableICPFilters: true, currentStep: "create-icp-rubric", watchNarration })`
|
|
273
274
|
before rubric thinking or branch work. The watched app should move to Filter
|
|
274
|
-
Rules quickly. After `save_rubrics`, the
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
275
|
+
Rules quickly. After `save_rubrics`, keep the app on Filter Rules so the user
|
|
276
|
+
can read and approve the saved criteria. Only after that approval should
|
|
277
|
+
`update_campaign` move to `apply-icp-rubric` / Filter Leads, where the run waits
|
|
278
|
+
for the message template approval before enrichment, filtering, or Generate
|
|
279
|
+
Message cells are queued. Tell the user the Message Draft Builder is preparing
|
|
280
|
+
the template in the background.
|
|
279
281
|
|
|
280
282
|
Lead Fit Builder persists production rubrics with `save_rubrics` when filters
|
|
281
283
|
are enabled. It must not require `brief.md`, `lead-review.md`, or
|
|
@@ -311,11 +313,11 @@ state before drafting. Do not render message review until
|
|
|
311
313
|
|
|
312
314
|
Load references only when needed:
|
|
313
315
|
|
|
314
|
-
- `references/watch-link-handoff.md` for watch-link
|
|
315
|
-
- `references/watch-guide-narration.md` for
|
|
316
|
+
- `references/watch-link-handoff.md` for watch-link handoff.
|
|
317
|
+
- `references/watch-guide-narration.md` for watch narration.
|
|
316
318
|
- `references/lead-validation-preview.md` for legacy/debug preview shapes.
|
|
317
319
|
- `references/filter-leads.md` for rubric design and `save_rubrics` rules.
|
|
318
|
-
- `references/step-13-import-leads.md` before
|
|
320
|
+
- `references/step-13-import-leads.md` before source copy.
|
|
319
321
|
- `references/sample-validation-loop.md` before review-batch validation.
|
|
320
322
|
- `references/final-handoff-contract.md` for Settings, sender, sequence, and
|
|
321
323
|
start.
|