@sellable/mcp 0.1.155 → 0.1.157
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/agents/source-scout-linkedin-engagement.md +29 -24
- package/dist/tools/leads.js +19 -19
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +25 -19
- package/skills/create-campaign-v2/SKILL.md +25 -22
- package/skills/create-campaign-v2/SOUL.md +6 -6
- package/skills/create-campaign-v2/core/flow.v2.json +4 -4
- package/skills/create-campaign-v2/references/filter-leads.md +3 -3
- package/skills/create-campaign-v2/references/step-13-import-leads.md +10 -9
- package/skills/create-campaign-v2-tail/SKILL.md +2 -2
- package/skills/providers/signal-discovery.md +24 -20
|
@@ -51,14 +51,15 @@ currentStep: "signal-discovery" })` before sampling so the watched Signal
|
|
|
51
51
|
visible headline/display-name cues only. Do not enrich people during
|
|
52
52
|
viability estimation.
|
|
53
53
|
7. Compute capacity before recommending the source: source target good-fit
|
|
54
|
-
leads (default
|
|
55
|
-
reachable engagers,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
leads (default 300 for Signal Discovery unless the parent supplies a target),
|
|
55
|
+
reachable engagers, sampled headline-fit rate as `n/N` plus an easy
|
|
56
|
+
percentage/range, expected headline-fit prospects per 100 engagers, required
|
|
57
|
+
engagers to scrape (`source target / sampled headline-fit rate`), average
|
|
58
|
+
reachable engagers per right-content post, expected headline-fit prospects
|
|
59
|
+
per right-content post, posts needed to hit the target, and whether
|
|
60
|
+
sampled/projected headline-fit rate clears the 10% planning floor. Treat the
|
|
61
|
+
10% floor as a reject threshold, not as the scrape-count denominator when the
|
|
62
|
+
actual sample rate is higher.
|
|
62
63
|
8. Select/promote enough right-content posts to plausibly hit the target. If the
|
|
63
64
|
warm Signals pool is useful but too small, return the expected warm range and
|
|
64
65
|
recommend Sales Nav/Prospeo for scale instead of padding with noisy posts.
|
|
@@ -72,12 +73,12 @@ Return a concise structured result with:
|
|
|
72
73
|
- `selected_posts` with URL/title, author/topic, age, engager count, sampled engagers, good fits as n/N, estimated usable prospects per post, use/discard
|
|
73
74
|
- `sample_leads`, if any
|
|
74
75
|
- `approval_math` with eligible posts, source target good-fit leads, sampled
|
|
75
|
-
engagers,
|
|
76
|
-
100 engagers, required engagers to scrape, average reachable
|
|
77
|
-
post, expected
|
|
78
|
-
target, whether the 10% planning floor clears
|
|
79
|
-
|
|
80
|
-
fallback
|
|
76
|
+
engagers, headline-fit rate as `n/N` plus percentage/range, headline-fit
|
|
77
|
+
prospects per 100 engagers, required engagers to scrape, average reachable
|
|
78
|
+
engagers per post, expected headline-fit prospects per post, posts needed for
|
|
79
|
+
target, whether the 10% planning floor clears, selected post count, internal
|
|
80
|
+
campaign-table execution-slice size, expected headline-fit lead range, and
|
|
81
|
+
scale fallback
|
|
81
82
|
- `estimated_good_fit_range`
|
|
82
83
|
- `message_context_strength`, directional and source-specific
|
|
83
84
|
- `false_positive_patterns`
|
|
@@ -93,14 +94,18 @@ Evidence standards:
|
|
|
93
94
|
GTM/outbound/buyer pain, workflow, or role context that makes the campaign
|
|
94
95
|
relevant.
|
|
95
96
|
- Do not make the user infer capacity. Say, plainly, how many eligible posts
|
|
96
|
-
exist, how many sampled engagers
|
|
97
|
-
that implies per 100 engagers, how many
|
|
98
|
-
post should yield
|
|
99
|
-
300-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
exist, how many sampled engagers passed the headline ICP rubric, what
|
|
98
|
+
headline-fit rate that implies per 100 engagers, how many headline-fit
|
|
99
|
+
prospects one right-content post should yield, how many engagers must be
|
|
100
|
+
scraped for the 300 headline-fit source target using the sampled pass rate
|
|
101
|
+
(or the 20% working assumption only when there is no stronger sample), how
|
|
102
|
+
many posts are needed for that source target, and which posts you would use.
|
|
103
|
+
Also say the source list is copied into the campaign and only the first
|
|
104
|
+
campaign-table execution slice is processed internally for filter and message
|
|
105
|
+
setup.
|
|
103
106
|
- If `fetch_post_engagers` is unavailable or fails, report that explicitly and mark the estimate lower-confidence.
|
|
104
|
-
- Keep LinkedIn Engagement viable when selected posts can produce roughly 300+
|
|
105
|
-
-
|
|
106
|
-
|
|
107
|
+
- Keep LinkedIn Engagement viable when selected posts can produce roughly 300+
|
|
108
|
+
headline-fit warm prospects before final filtering, even if Sales Nav is more
|
|
109
|
+
scalable.
|
|
110
|
+
- If sampled/projected headline-fit rate is below 10%, reject the Signals
|
|
111
|
+
scrape path and recommend Sales Nav recent activity as the next source.
|
package/dist/tools/leads.js
CHANGED
|
@@ -725,8 +725,8 @@ function buildFilterChoiceWatchNarration({ sourceLeadCount, reviewRowCount, samp
|
|
|
725
725
|
function buildSignalDiscoverySearchWatchNarration() {
|
|
726
726
|
return {
|
|
727
727
|
stage: "find-leads",
|
|
728
|
-
headline: "Searching
|
|
729
|
-
visibleState: "The browser is showing
|
|
728
|
+
headline: "Searching LinkedIn posts",
|
|
729
|
+
visibleState: "The browser is showing the LinkedIn post search step while approved themes run.",
|
|
730
730
|
agentIntent: "Codex is searching the approved post themes and will ask before scraping selected engagers into a source list.",
|
|
731
731
|
nextAction: "Review selected posts before scraping",
|
|
732
732
|
safety: "Scrape approval is the next gate.",
|
|
@@ -734,11 +734,11 @@ function buildSignalDiscoverySearchWatchNarration() {
|
|
|
734
734
|
}
|
|
735
735
|
function buildSignalDiscoveryResultsWatchNarration(postsReturned) {
|
|
736
736
|
const postCopy = typeof postsReturned === "number"
|
|
737
|
-
? `${postsReturned.toLocaleString("en-US")} post${postsReturned === 1 ? "" : "s"} matched the approved search themes and are visible
|
|
738
|
-
: "
|
|
737
|
+
? `${postsReturned.toLocaleString("en-US")} post${postsReturned === 1 ? "" : "s"} matched the approved search themes and are visible for review.`
|
|
738
|
+
: "LinkedIn post results are visible for review.";
|
|
739
739
|
return {
|
|
740
740
|
stage: "find-leads",
|
|
741
|
-
headline: "Review
|
|
741
|
+
headline: "Review LinkedIn posts",
|
|
742
742
|
visibleState: postCopy,
|
|
743
743
|
agentIntent: "Codex is promoting the strongest posts, then it will ask before scraping the selected engager pool.",
|
|
744
744
|
nextAction: "Approve selected posts before scraping",
|
|
@@ -749,9 +749,9 @@ function buildSelectedPostApprovalWatchNarration(selectedPostCount) {
|
|
|
749
749
|
return {
|
|
750
750
|
stage: "find-leads",
|
|
751
751
|
headline: "Approve selected-post scrape",
|
|
752
|
-
visibleState: `${selectedPostCount.toLocaleString("en-US")} LinkedIn post${selectedPostCount === 1 ? "" : "s"} selected
|
|
752
|
+
visibleState: `${selectedPostCount.toLocaleString("en-US")} LinkedIn post${selectedPostCount === 1 ? "" : "s"} selected for the source test.`,
|
|
753
753
|
agentIntent: "Codex is asking before scraping this selected engager pool into a source list.",
|
|
754
|
-
nextAction: `Approve scraping ${selectedPostCount.toLocaleString("en-US")}
|
|
754
|
+
nextAction: `Approve scraping ${selectedPostCount.toLocaleString("en-US")} selected LinkedIn post${selectedPostCount === 1 ? "" : "s"}`,
|
|
755
755
|
safety: "Scrape approval is the next gate.",
|
|
756
756
|
};
|
|
757
757
|
}
|
|
@@ -775,12 +775,12 @@ function buildSignalDiscoverySourceRecommendation({ selectedPosts, }) {
|
|
|
775
775
|
const estimatedGoodFit = totalEngagement * defaultFitRate;
|
|
776
776
|
return `## Source Recommendation
|
|
777
777
|
|
|
778
|
-
Use
|
|
778
|
+
Use LinkedIn engagement first.
|
|
779
779
|
|
|
780
|
-
**Goal:** ~${targetGoodFitLeads.toLocaleString("en-US")}
|
|
781
|
-
**Working assumption:** ~${Math.round(defaultFitRate * 100)}% of raw post engagers
|
|
780
|
+
**Goal:** ~${targetGoodFitLeads.toLocaleString("en-US")} headline-fit prospects from relevant LinkedIn engagement<br>
|
|
781
|
+
**Working assumption:** ~${Math.round(defaultFitRate * 100)}% of raw post engagers pass headline filtering unless a real sample supports a different rate<br>
|
|
782
782
|
**Engagers needed:** ~${sourceCandidateTarget.toLocaleString("en-US")} raw engagers<br>
|
|
783
|
-
**Planning floor:** continue with
|
|
783
|
+
**Planning floor:** continue with LinkedIn engagement only when sampled/projected headline-fit rate is at least ${Math.round(minPlanningFitRate * 100)}%; below that, switch to Sales Nav recent activity<br>
|
|
784
784
|
**Review checkpoint:** copy the confirmed source list into the campaign, then process the first ${reviewBatchSize.toLocaleString("en-US")} leads for fit and message review before scaling
|
|
785
785
|
|
|
786
786
|
### Selected posts
|
|
@@ -790,21 +790,21 @@ Use Signal Discovery first.
|
|
|
790
790
|
${tableRows || "| Selected posts | Campaign-matched public engagement | - |"}
|
|
791
791
|
|
|
792
792
|
**Total visible pool:** ${formatApproxInteger(totalEngagement)} engagers<br>
|
|
793
|
-
**Estimated
|
|
793
|
+
**Estimated headline-fit pool at ${Math.round(defaultFitRate * 100)}%:** ${formatApproxInteger(estimatedGoodFit)} prospects before enrichment and deeper fit review
|
|
794
794
|
|
|
795
795
|
### Recommendation
|
|
796
796
|
|
|
797
797
|
Approve scraping these ${selectedCount} posts.
|
|
798
798
|
|
|
799
|
-
This gives enough volume to target ~${targetGoodFitLeads.toLocaleString("en-US")}
|
|
799
|
+
This gives enough volume to target ~${targetGoodFitLeads.toLocaleString("en-US")} headline-fit prospects, while keeping the source tied to people already engaging with the campaign's strongest public buying signals.
|
|
800
800
|
|
|
801
801
|
**First pass:** build the source list, copy it into the campaign, then use the first ${reviewBatchSize.toLocaleString("en-US")} campaign rows as the internal setup slice for filters and messages before scaling.
|
|
802
802
|
|
|
803
|
-
**Fallback:** if the sampled/projected fit rate is below ${Math.round(minPlanningFitRate * 100)}%, or if the source sample is too vendor-heavy, agency-heavy, or off-ICP, switch to Sales Nav recent activity.
|
|
803
|
+
**Fallback:** if the sampled/projected headline-fit rate is below ${Math.round(minPlanningFitRate * 100)}%, or if the source sample is too vendor-heavy, agency-heavy, or off-ICP, switch to Sales Nav recent activity.
|
|
804
804
|
|
|
805
805
|
Approval card should say:
|
|
806
806
|
|
|
807
|
-
**Approve scraping ${selectedCount}
|
|
807
|
+
**Approve scraping ${selectedCount} selected LinkedIn post${selectedCount === 1 ? "" : "s"}?**`;
|
|
808
808
|
}
|
|
809
809
|
function normalizeImportProvider(provider) {
|
|
810
810
|
if (provider === "apollo-ai" || provider === "apollo")
|
|
@@ -1390,7 +1390,7 @@ export const leadToolDefinitions = [
|
|
|
1390
1390
|
},
|
|
1391
1391
|
targetEngagerCount: {
|
|
1392
1392
|
type: "number",
|
|
1393
|
-
description: "Signal Discovery: target number of post engagers/source candidates to scrape. Default planning target is about 300
|
|
1393
|
+
description: "Signal Discovery: target number of post engagers/source candidates to scrape. Default planning target is about 300 headline-fit prospects at a 20% raw-engager headline-pass assumption, or about 1500 engagers. Use real sample math when available: target headline-fit prospects divided by sampled headline-pass rate. If the sampled/projected headline-fit rate is below the 10% planning floor, switch to the next provider instead of scaling noisy engagers. Limits selected posts before starting scrape, with a backend hard cap of 10 posts.",
|
|
1394
1394
|
},
|
|
1395
1395
|
maxPostsToScrape: {
|
|
1396
1396
|
type: "number",
|
|
@@ -3089,15 +3089,15 @@ export async function selectPromisingPosts(input) {
|
|
|
3089
3089
|
const { reviewBatchSize } = getSignalDiscoverySourcePlanDefaults();
|
|
3090
3090
|
sourceRecommendation = `## Source Recommendation
|
|
3091
3091
|
|
|
3092
|
-
Use
|
|
3092
|
+
Use LinkedIn engagement first.
|
|
3093
3093
|
|
|
3094
|
-
**Recommendation:** approve scraping the ${selectionResult.selectedCount} selected
|
|
3094
|
+
**Recommendation:** approve scraping the ${selectionResult.selectedCount} selected LinkedIn post${selectionResult.selectedCount === 1 ? "" : "s"}.
|
|
3095
3095
|
|
|
3096
3096
|
**First pass:** build the source list, copy it into the campaign, then process only the first ${reviewBatchSize.toLocaleString("en-US")} leads so we can inspect quality before scaling.
|
|
3097
3097
|
|
|
3098
3098
|
Approval card should say:
|
|
3099
3099
|
|
|
3100
|
-
**Approve scraping ${selectionResult.selectedCount}
|
|
3100
|
+
**Approve scraping ${selectionResult.selectedCount} selected LinkedIn post${selectionResult.selectedCount === 1 ? "" : "s"}?**`;
|
|
3101
3101
|
}
|
|
3102
3102
|
return {
|
|
3103
3103
|
success: true,
|
package/package.json
CHANGED
|
@@ -139,10 +139,12 @@ should say:
|
|
|
139
139
|
- what approval covers in one concise line
|
|
140
140
|
|
|
141
141
|
Do not surface blanket source heuristics as product copy. Make the
|
|
142
|
-
recommendation specific to the campaign. If
|
|
143
|
-
name the exact post themes you will search
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
recommendation specific to the campaign. If LinkedIn engagement is recommended,
|
|
143
|
+
name the exact post themes you will search and avoid using "Signal Discovery" in
|
|
144
|
+
customer-facing chat; that is the internal provider/app label. If relevant
|
|
145
|
+
public conversations look unlikely, recommend the specific Sales Nav or Prospeo
|
|
146
|
+
lane instead and say why. Do not call `search_signals`, `search_sales_nav`,
|
|
147
|
+
`search_prospeo`,
|
|
146
148
|
`fetch_post_engagers`, or provider-scoped subagents until the user approves this
|
|
147
149
|
source plan or explicitly chooses a different source.
|
|
148
150
|
|
|
@@ -161,10 +163,11 @@ precision, and referral paths, but it does not provide hiring-by-role filters;
|
|
|
161
163
|
say that distinction plainly in the source-plan gate.
|
|
162
164
|
|
|
163
165
|
After scouting, ask for a second approval on the concrete source action. For
|
|
164
|
-
|
|
165
|
-
target engager/source-candidate volume. For
|
|
166
|
-
specific approved import lane and source lead
|
|
167
|
-
15-row campaign-table execution slice separate from
|
|
166
|
+
LinkedIn engagement (`signal-discovery` internally), name how many selected
|
|
167
|
+
posts will be scraped and the target engager/source-candidate volume. For
|
|
168
|
+
Sales Nav or Prospeo, name the specific approved import lane and source lead
|
|
169
|
+
count. Keep the internal 15-row campaign-table execution slice separate from
|
|
170
|
+
source sampling.
|
|
168
171
|
|
|
169
172
|
Do not call `import_leads` or `confirm_lead_list` until this second approval is
|
|
170
173
|
granted.
|
|
@@ -181,26 +184,29 @@ granted.
|
|
|
181
184
|
should `confirm_lead_list({ reviewBatchLimit: 15 })` copy confirmed rows into
|
|
182
185
|
the campaign table and return the initial campaign-table execution slice rows.
|
|
183
186
|
|
|
184
|
-
For
|
|
185
|
-
action shape "Approve scraping N
|
|
187
|
+
For LinkedIn engagement, the customer-facing approval card must use the exact
|
|
188
|
+
action shape "Approve scraping N selected LinkedIn posts?" and the chat summary
|
|
186
189
|
should be a compact `## Source Recommendation` block with:
|
|
187
190
|
|
|
188
|
-
- goal: about 300
|
|
189
|
-
- source-candidate plan:
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
- goal: about 300 headline-fit prospects from relevant LinkedIn engagement
|
|
192
|
+
- source-candidate plan: use sample math first: target headline-fit prospects
|
|
193
|
+
divided by sampled headline-pass rate. If there is no stronger sample, use
|
|
194
|
+
about 1,500 raw engagers from the 20% working headline-pass assumption.
|
|
195
|
+
- planning floor: continue with LinkedIn engagement only when sampled/projected
|
|
196
|
+
headline-fit rate is at least 10%; below that, move to Sales Nav recent
|
|
197
|
+
activity instead of scraping noisy engagers. Do not use the 10% floor as the
|
|
198
|
+
scrape-count denominator when the actual sample rate is higher.
|
|
194
199
|
- campaign setup checkpoint: after the source list exists, copy confirmed source rows
|
|
195
200
|
into the campaign and internally process the first execution slice for fit and message setup
|
|
196
201
|
- a selected-post table with post author/topic, why it fits, and visible
|
|
197
202
|
engagement
|
|
198
|
-
- total visible pool and estimated
|
|
203
|
+
- total visible pool and estimated headline-fit pool
|
|
199
204
|
- first pass: build the source list and copy all confirmed source rows into the
|
|
200
205
|
campaign; the campaign table then internally processes its first execution
|
|
201
206
|
slice before scaling
|
|
202
|
-
- fallback: switch to Sales Nav recent activity if sampled/projected
|
|
203
|
-
below 10%, or if the source sample is vendor-heavy,
|
|
207
|
+
- fallback: switch to Sales Nav recent activity if sampled/projected
|
|
208
|
+
headline-fit rate falls below 10%, or if the source sample is vendor-heavy,
|
|
209
|
+
agency-heavy, or off-ICP
|
|
204
210
|
|
|
205
211
|
When the user has not supplied a source and multiple source angles are viable,
|
|
206
212
|
scout those angles as independent branches when the host can actually do it:
|
|
@@ -133,7 +133,7 @@ copy.
|
|
|
133
133
|
|
|
134
134
|
Default source order when the user has not supplied a source:
|
|
135
135
|
|
|
136
|
-
1. LinkedIn post engagement
|
|
136
|
+
1. LinkedIn post engagement (internal provider: `signal-discovery`)
|
|
137
137
|
2. Sales Nav recent activity
|
|
138
138
|
3. broader Sales Nav role/title filters
|
|
139
139
|
4. Prospeo account/contact expansion
|
|
@@ -160,12 +160,14 @@ the question, and this first approval authorizes source scouting/search only:
|
|
|
160
160
|
- that approval authorizes scouting/search only, not lead import or sending
|
|
161
161
|
|
|
162
162
|
Do not surface blanket source heuristics as product copy. Make the recommendation
|
|
163
|
-
specific to the campaign. If
|
|
164
|
-
post themes you will search
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
163
|
+
specific to the campaign. If LinkedIn engagement is recommended, name the exact
|
|
164
|
+
post themes you will search and avoid using "Signal Discovery" in
|
|
165
|
+
customer-facing chat; that is the internal provider/app label. If the campaign
|
|
166
|
+
looks unlikely to have relevant public conversations, recommend the specific
|
|
167
|
+
Sales Nav or Prospeo lane instead and say why. An approval like "Approve Prospeo
|
|
168
|
+
plan" satisfies this gate; persist the provider and search next. Do not ask a
|
|
169
|
+
second source-plan question. Do not call `search_signals`, `search_sales_nav`,
|
|
170
|
+
`search_prospeo`,
|
|
169
171
|
`fetch_post_engagers`, or provider-scoped subagents until the user approves this
|
|
170
172
|
source plan or explicitly chooses a different source.
|
|
171
173
|
|
|
@@ -174,18 +176,19 @@ sequential by default. Run `source-scout-linkedin-engagement`,
|
|
|
174
176
|
`source-scout-sales-nav`, and `source-scout-prospeo-contact` in parallel only
|
|
175
177
|
when the user explicitly requested source comparison, a prior lane failed, or
|
|
176
178
|
the first viable lane is borderline and a cheap fallback check is needed.
|
|
177
|
-
Use a 10% planning floor after conservative cleanup. If
|
|
178
|
-
below that floor, move to Sales Nav. If Sales Nav falls below that floor
|
|
179
|
-
reasonable refinement, move to Prospeo. Prospeo is the terminal fallback;
|
|
180
|
-
also falls below 10%, tighten the ICP/source direction instead of
|
|
181
|
-
another provider.
|
|
179
|
+
Use a 10% planning floor after conservative cleanup. If LinkedIn engagement
|
|
180
|
+
falls below that floor, move to Sales Nav. If Sales Nav falls below that floor
|
|
181
|
+
after reasonable refinement, move to Prospeo. Prospeo is the terminal fallback;
|
|
182
|
+
if it also falls below 10%, tighten the ICP/source direction instead of
|
|
183
|
+
inventing another provider.
|
|
182
184
|
|
|
183
185
|
After scouting, show a second approval gate for the concrete source action.
|
|
184
|
-
For
|
|
185
|
-
volume, internal campaign-table
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
not call `import_leads` or
|
|
186
|
+
For LinkedIn engagement (`signal-discovery` internally), state selected-post
|
|
187
|
+
count, target engager/source-candidate volume, internal campaign-table
|
|
188
|
+
execution-slice size, cleanup risk, and fallback; label the approval like
|
|
189
|
+
"Approve scraping 3 selected LinkedIn posts?" For Sales Nav or Prospeo, name the
|
|
190
|
+
specific search/import lane and source lead count. Do not call `import_leads` or
|
|
191
|
+
`confirm_lead_list` until this gate is approved.
|
|
189
192
|
|
|
190
193
|
For Sales Nav and Prospeo, do not ask to import only the internal 15-row
|
|
191
194
|
campaign-table execution slice at the source-action gate. First-page samples are
|
|
@@ -205,18 +208,18 @@ export count, not the campaign execution-slice size. For Signal Discovery, pass
|
|
|
205
208
|
`confirmed: true`; the tool owns moving the watch UI to source-list progress
|
|
206
209
|
after a lead-list/job id exists.
|
|
207
210
|
|
|
208
|
-
For
|
|
211
|
+
For LinkedIn engagement, use this compact source-action approval shape after
|
|
209
212
|
selected posts exist:
|
|
210
213
|
|
|
211
214
|
```markdown
|
|
212
215
|
## Source Recommendation
|
|
213
216
|
|
|
214
|
-
Use
|
|
217
|
+
Use LinkedIn engagement first.
|
|
215
218
|
|
|
216
|
-
**Goal:** ~300
|
|
217
|
-
**Working assumption:** ~20% of raw post engagers
|
|
219
|
+
**Goal:** ~300 headline-fit prospects from relevant LinkedIn engagement<br>
|
|
220
|
+
**Working assumption:** ~20% of raw post engagers pass headline filtering unless a real sample supports a different rate<br>
|
|
218
221
|
**Engagers needed:** ~1,500 raw engagers<br>
|
|
219
|
-
**Planning floor:** continue only when sampled/projected fit is at least 10
|
|
222
|
+
**Planning floor:** continue only when sampled/projected headline-fit rate is at least 10%; below that, switch to Sales Nav recent activity<br>
|
|
220
223
|
**Campaign setup checkpoint:** after the source list exists, copy the entire confirmed source list into the campaign and internally process only the first execution slice for filter and message setup<br>
|
|
221
224
|
|
|
222
225
|
### Selected posts
|
|
@@ -239,12 +239,12 @@ source. That approval only authorizes scouting/search. Second, after the
|
|
|
239
239
|
source evidence exists, show counts, samples, fit math, cleanup risk, and ask
|
|
240
240
|
for source approval before import.
|
|
241
241
|
|
|
242
|
-
For
|
|
242
|
+
For LinkedIn engagement, the second gate is not "approve source" in the abstract.
|
|
243
243
|
It is a concrete scrape approval: show a compact `## Source Recommendation`
|
|
244
|
-
with the ~
|
|
245
|
-
table, total visible pool, estimated
|
|
244
|
+
with the ~300 headline-fit prospect goal, source sample assumption, selected-post
|
|
245
|
+
table, total visible pool, estimated headline-fit pool, 10% planning floor,
|
|
246
246
|
first-pass campaign setup, and fallback. The approval question should be "Approve
|
|
247
|
-
scraping N
|
|
247
|
+
scraping N selected LinkedIn posts?"
|
|
248
248
|
|
|
249
249
|
That scrape approval is single-use. Once the user approves it, do not replay
|
|
250
250
|
the source card or ask for the same approval again. Acknowledge the approval in
|
|
@@ -254,13 +254,13 @@ one sentence and call `import_leads` for the approved source immediately.
|
|
|
254
254
|
|
|
255
255
|
Source selection is sequential by default. Start with the first recommended
|
|
256
256
|
source lane from `flow.v2.json`; for the current campaign shape that is usually
|
|
257
|
-
|
|
257
|
+
LinkedIn engagement. Only try the next fallback after the
|
|
258
258
|
current lane is not viable, the user asks for a comparison, or the first lane is
|
|
259
259
|
borderline and needs a second source to avoid a bad recommendation. The fallback
|
|
260
260
|
order must stay plain: use Sales Nav to find ICP people who are actively posting
|
|
261
261
|
on LinkedIn; if that is not enough, search Sales Nav by titles; if that is still
|
|
262
262
|
not enough, use Prospeo for a broader account/contact path.
|
|
263
|
-
Use a 10% planning floor after conservative cleanup. If
|
|
263
|
+
Use a 10% planning floor after conservative cleanup. If LinkedIn engagement falls
|
|
264
264
|
below that floor, move to Sales Nav. If Sales Nav falls below that floor after
|
|
265
265
|
reasonable refinement, move to Prospeo. Prospeo is the terminal fallback; if it
|
|
266
266
|
also falls below 10%, tighten the ICP/source direction instead of inventing
|
|
@@ -399,14 +399,14 @@
|
|
|
399
399
|
"what approval authorizes"
|
|
400
400
|
],
|
|
401
401
|
"choices": [
|
|
402
|
-
"Approve
|
|
402
|
+
"Approve LinkedIn engagement scouting plan",
|
|
403
403
|
"Approve Sales Nav scouting plan",
|
|
404
404
|
"Approve Prospeo scouting plan",
|
|
405
405
|
"Choose different source",
|
|
406
406
|
"Pause here"
|
|
407
407
|
],
|
|
408
408
|
"approvalChoiceLabelsByProvider": {
|
|
409
|
-
"signal-discovery": "Approve
|
|
409
|
+
"signal-discovery": "Approve LinkedIn engagement scouting plan",
|
|
410
410
|
"sales-nav": "Approve Sales Nav scouting plan",
|
|
411
411
|
"prospeo": "Approve Prospeo scouting plan"
|
|
412
412
|
},
|
|
@@ -508,13 +508,13 @@
|
|
|
508
508
|
"action": "ask_source_review_choice",
|
|
509
509
|
"uses": "request_user_input",
|
|
510
510
|
"choices": [
|
|
511
|
-
"Approve scraping N
|
|
511
|
+
"Approve scraping N selected LinkedIn posts",
|
|
512
512
|
"Run the approved source import",
|
|
513
513
|
"Revise source",
|
|
514
514
|
"Pause here"
|
|
515
515
|
],
|
|
516
516
|
"approvalChoiceLabelsByProvider": {
|
|
517
|
-
"signal-discovery": "Approve scraping {selectedPostCount}
|
|
517
|
+
"signal-discovery": "Approve scraping {selectedPostCount} selected LinkedIn posts?",
|
|
518
518
|
"sales-nav": "Import the approved Sales Nav source list",
|
|
519
519
|
"prospeo": "Import the approved Prospeo source list"
|
|
520
520
|
},
|
|
@@ -152,9 +152,9 @@ Use this test:
|
|
|
152
152
|
- Did the campaign rows show adjacent companies that the customer would likely
|
|
153
153
|
reject only after seeing the list?
|
|
154
154
|
|
|
155
|
-
If yes, add an explicit exclude rule. Include named competitors
|
|
156
|
-
campaign rows, or user context when available, plus the general
|
|
157
|
-
exclusion so new lookalike competitors are also blocked.
|
|
155
|
+
If yes, add an explicit exclude rule. Use the review batch as evidence. Include named competitors
|
|
156
|
+
from the brief, campaign rows, or user context when available, plus the general
|
|
157
|
+
category exclusion so new lookalike competitors are also blocked.
|
|
158
158
|
|
|
159
159
|
## Marketplace Safety
|
|
160
160
|
|
|
@@ -107,7 +107,7 @@ import_leads({
|
|
|
107
107
|
campaignOfferId,
|
|
108
108
|
targetLeadCount: <sourceCandidateTarget from approved good-fit math>,
|
|
109
109
|
// Signal Discovery only:
|
|
110
|
-
targetEngagerCount: <ceil(
|
|
110
|
+
targetEngagerCount: <ceil(targetHeadlineFitProspects / sampledHeadlinePassRate)>,
|
|
111
111
|
maxPostsToScrape: <postsNeeded from approved math>
|
|
112
112
|
})
|
|
113
113
|
```
|
|
@@ -124,14 +124,15 @@ escalation logic so dedup ratios are visible.
|
|
|
124
124
|
|
|
125
125
|
For Signal Discovery, do not scrape every currently selected/promoted sample
|
|
126
126
|
post by default. Before `import_leads`, reconcile selected posts with the
|
|
127
|
-
approved source math. The default
|
|
128
|
-
|
|
129
|
-
raw engagers. If the sampled fit rate is stronger or weaker, use
|
|
130
|
-
|
|
131
|
-
approved provider limit, and select only
|
|
132
|
-
count. The planning floor is 10% projected
|
|
133
|
-
Discovery falls below that floor during the
|
|
134
|
-
plan before importing. After an approved
|
|
127
|
+
approved source math. The default headline-fit target is 300 and the planning
|
|
128
|
+
headline-pass assumption is 20%, so the default source-candidate plan is about
|
|
129
|
+
1,500 raw engagers. If the sampled headline-fit rate is stronger or weaker, use
|
|
130
|
+
that sampled rate for `ceil(targetHeadlineFitProspects / sampledHeadlinePassRate)`,
|
|
131
|
+
cap the source candidates at the approved provider limit, and select only
|
|
132
|
+
enough posts to reach that engager count. The planning floor is 10% projected
|
|
133
|
+
headline-fit rate; if Signal Discovery falls below that floor during the
|
|
134
|
+
pre-scrape sample, revise the source plan before importing. After an approved
|
|
135
|
+
scrape starts, do not discard a nonempty
|
|
135
136
|
completed source list just because it lands below the source-candidate target:
|
|
136
137
|
confirm/copy the completed list for campaign setup, then add more posts
|
|
137
138
|
or switch provider if the source quality or scale is not enough. The subsequent
|
|
@@ -236,14 +236,14 @@ campaignOfferId, confirmed: true })` -> `search_signals({ campaignOfferId,
|
|
|
236
236
|
selectionMode: "replace", selections, headlineICPCriteria })` ->
|
|
237
237
|
`import_leads({ campaignOfferId, provider: "signal-discovery",
|
|
238
238
|
targetEngagerCount: 1500 })`.
|
|
239
|
-
For
|
|
239
|
+
For LinkedIn engagement (`signal-discovery` internally), the promotion/select step is load-bearing. Use
|
|
240
240
|
post IDs from the current campaign-scoped `search_signals` response or
|
|
241
241
|
posts the user has visibly promoted in the campaign UI. Never use post IDs
|
|
242
242
|
copied only from a source-scout summary unless they have been re-resolved
|
|
243
243
|
through the current campaign search state. After `select_promising_posts`,
|
|
244
244
|
require `selectedCount > 0` before calling `import_leads`. If it returns
|
|
245
245
|
`selectedCount: 0`, do not switch providers and do not retry import.
|
|
246
|
-
Explain that the campaign has no promoted
|
|
246
|
+
Explain that the campaign has no promoted LinkedIn posts yet,
|
|
247
247
|
re-run a narrow campaign-scoped `search_signals` call to recover current
|
|
248
248
|
post rows, or ask the user to promote the desired posts in the UI and then
|
|
249
249
|
retry `import_leads`.
|
|
@@ -24,10 +24,12 @@ When the user asks to find posts or start searching, **IMMEDIATELY begin Round 1
|
|
|
24
24
|
|
|
25
25
|
<lead_target>
|
|
26
26
|
|
|
27
|
-
- **Default create-campaign target: ~300
|
|
28
|
-
|
|
29
|
-
- **
|
|
30
|
-
|
|
27
|
+
- **Default create-campaign target: ~300 headline-fit prospects that pass the
|
|
28
|
+
Signal Discovery headline criteria for now.**
|
|
29
|
+
- **Use sample math first: required raw engagers =
|
|
30
|
+
`ceil(targetHeadlineFitProspects / sampledHeadlinePassRate)`. When no
|
|
31
|
+
stronger sample exists, assume ~20% of raw post engagers pass headline
|
|
32
|
+
filtering, so plan around ~1,500 raw engagers.**
|
|
31
33
|
- Provider/import caps are internal execution limits, not customer-facing
|
|
32
34
|
promises. Do not tell the user the internal provider cap.
|
|
33
35
|
- Quality > Quantity: a few hundred active users > 1000 potentially inactive profiles
|
|
@@ -112,23 +114,24 @@ You must estimate:
|
|
|
112
114
|
- `passRate`
|
|
113
115
|
- sampled pass rate used for extrapolation
|
|
114
116
|
- `goodFitPer100Engagers`
|
|
115
|
-
- normalized
|
|
116
|
-
after a conservative dedupe/cleanup factor
|
|
117
|
+
- normalized headline-pass rate as headline-fit prospects per 100 engagers
|
|
117
118
|
- `avgReachableEngagersPerPost`
|
|
118
119
|
- average reachable engagers per right-content post used for capacity math
|
|
119
120
|
- `goodFitProspectsPerPost`
|
|
120
|
-
- expected
|
|
121
|
+
- expected headline-fit prospects per right-content post
|
|
121
122
|
- `postsNeededForTarget`
|
|
122
123
|
- number of right-content posts needed to reach the target good-fit lead
|
|
123
124
|
count, defaulting to 300 for Signal Discovery unless the campaign says
|
|
124
125
|
otherwise
|
|
125
126
|
- `requiredEngagersToScrape`
|
|
126
|
-
- `ceil(
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
- `ceil(targetHeadlineFitProspects / sampledHeadlinePassRate)`; for example
|
|
128
|
+
a 35/60 sample is ~58%, so a 300 headline-fit target needs about 515 raw
|
|
129
|
+
engagers before adding a practical coverage buffer, not 3,000. The 10%
|
|
130
|
+
floor is a viability reject threshold, not the denominator when the sample
|
|
131
|
+
rate is higher.
|
|
129
132
|
- `planningFloor`
|
|
130
|
-
- minimum acceptable sampled/projected fit rate
|
|
131
|
-
|
|
133
|
+
- minimum acceptable sampled/projected headline-fit rate; default 10%.
|
|
134
|
+
Below this, do not scale Signal Discovery.
|
|
132
135
|
- `projectedRange`
|
|
133
136
|
- the conservative range implied by the observed sample
|
|
134
137
|
|
|
@@ -152,10 +155,10 @@ Use conservative logic:
|
|
|
152
155
|
- stale posts
|
|
153
156
|
- adjacent communities that are not actual buyers
|
|
154
157
|
4. Explain the pass-through briefly and explicitly:
|
|
155
|
-
- preferred: "`sampledCount`: 40, `passCount`: 9, `passRate`: ~22%, `goodFitPer100Engagers`: ~22
|
|
158
|
+
- preferred: "`sampledCount`: 40, `passCount`: 9, `passRate`: ~22%, `goodFitPer100Engagers`: ~22 headline-fit prospects, `requiredEngagersToScrape`: ~1,365 raw engagers for a 300 headline-fit target before a practical coverage buffer, `avgReachableEngagersPerPost`: 240, `goodFitProspectsPerPost`: ~53, `postsNeededForTarget`: ~6, `recentStrongPostCount`: 15-25, `freshEnoughPostCount`: 8-12, `projectedRange`: 300-380 from selected posts"
|
|
156
159
|
- fallback: "I could not fetch engagers, so this is inferred from post and author quality only"
|
|
157
160
|
5. If the evidence is too weak, say so and return a low-confidence estimate instead of pretending precision.
|
|
158
|
-
6. If sampled/projected fit
|
|
161
|
+
6. If sampled/projected headline-fit rate is below the 10% planning floor,
|
|
159
162
|
reject the Signal Discovery scrape path and recommend Sales Nav recent
|
|
160
163
|
activity as the next source.
|
|
161
164
|
7. Do not manually enumerate dozens of engagers in the final answer. Summarize the sample by `sampledCount`, `passCount`, `passRate`, `projectedRange`, and 3-6 representative examples.
|
|
@@ -411,20 +414,21 @@ recommendation, estimate source capacity from real sample math:
|
|
|
411
414
|
campaign says otherwise)
|
|
412
415
|
- eligible right-content posts by lane/content type
|
|
413
416
|
- reachable engagers from those posts
|
|
414
|
-
- sampled
|
|
415
|
-
-
|
|
416
|
-
- required engagers to scrape for the source target
|
|
417
|
+
- sampled headline-fit rate as `n/N` plus an easy percentage/range
|
|
418
|
+
- headline-fit prospects per 100 engagers
|
|
419
|
+
- required engagers to scrape for the source target using the sampled
|
|
420
|
+
headline-fit rate
|
|
417
421
|
- average reachable engagers per right-content post
|
|
418
|
-
- expected
|
|
422
|
+
- expected headline-fit leads per selected post
|
|
419
423
|
- posts needed to reach the target
|
|
420
|
-
- whether sampled/projected fit clears the 10% planning floor
|
|
424
|
+
- whether sampled/projected headline-fit rate clears the 10% planning floor
|
|
421
425
|
|
|
422
426
|
Then select the smallest right-content post set that plausibly hits the source
|
|
423
427
|
target. Do not scrape every promoted sample post by default; promoted sampling
|
|
424
428
|
state and final scrape plan are separate. If the math says the warm post lane
|
|
425
429
|
only supports a smaller first batch, say that and name the Sales Nav or Prospeo
|
|
426
430
|
scale fallback rather than padding the selection with noisy posts. If the
|
|
427
|
-
sampled/projected fit rate is below 10
|
|
431
|
+
sampled/projected headline-fit rate is below 10%, do not call
|
|
428
432
|
`import_leads`; move to Sales Nav recent activity.
|
|
429
433
|
|
|
430
434
|
```json
|