@sellable/mcp 0.1.305 → 0.1.306

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.
@@ -1143,16 +1143,17 @@ function buildSignalDiscoverySourceRecommendation({ selectedPosts, targetEngager
1143
1143
  const recommendedCount = recommendedPosts.length;
1144
1144
  const totalVisibleEngagement = normalizedSelectedPosts.reduce((sum, post) => sum + post.likes + post.comments, 0);
1145
1145
  const recommendedVisibleEngagement = recommendedPosts.reduce((sum, post) => sum + post.likes + post.comments, 0);
1146
+ const fitRateForEstimate = targetEngagerCount && effectiveTargetEngagerCount > 0
1147
+ ? Math.min(1, targetGoodFitLeads / effectiveTargetEngagerCount)
1148
+ : defaultFitRate;
1149
+ const estimatedGoodFit = scrapePlan.estimatedEngagers * fitRateForEstimate;
1146
1150
  const tableRows = recommendedPosts
1147
1151
  .map((post) => {
1148
1152
  const engagement = post.likes + post.comments;
1149
- return `| ${escapeMarkdownTableCell(post.authorName)} | ${escapeMarkdownTableCell(post.reason)} | ${formatApproxInteger(engagement)} | ${formatApproxInteger(estimateScrapableSignalEngagers(post))} |`;
1153
+ const estimatedPostGoodFit = estimateScrapableSignalEngagers(post) * fitRateForEstimate;
1154
+ return `| ${escapeMarkdownTableCell(post.authorName)} | ${escapeMarkdownTableCell(post.reason)} | ${formatApproxInteger(engagement)} | ${formatApproxInteger(estimatedPostGoodFit)} |`;
1150
1155
  })
1151
1156
  .join("\n");
1152
- const fitRateForEstimate = targetEngagerCount && effectiveTargetEngagerCount > 0
1153
- ? Math.min(1, targetGoodFitLeads / effectiveTargetEngagerCount)
1154
- : defaultFitRate;
1155
- const estimatedGoodFit = scrapePlan.estimatedEngagers * fitRateForEstimate;
1156
1157
  const fitRateLabel = targetEngagerCount && effectiveTargetEngagerCount > 0
1157
1158
  ? "the approved buyer-search target"
1158
1159
  : `the ${Math.round(defaultFitRate * 100)}% starting estimate`;
@@ -1172,7 +1173,7 @@ I found ${recommendedCount.toLocaleString("en-US")} recommended LinkedIn post${r
1172
1173
 
1173
1174
  ### Recommended posts
1174
1175
 
1175
- | Post | Why this post | Public activity | People we can check |
1176
+ | Post | Why this post | Public activity | Est. likely prospects |
1176
1177
  |---|---|---:|---:|
1177
1178
  ${tableRows || "| Recommended posts | Campaign-matched public activity | - | - |"}
1178
1179
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.305",
3
+ "version": "0.1.306",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -406,8 +406,11 @@ summary should be a compact `## Source Recommendation` block with:
406
406
  - first review: after the source list exists, add confirmed source rows to the
407
407
  campaign and review the first 15 leads before scaling
408
408
  - a selected-post table with post author/topic, why it fits, public activity,
409
- and people we can check
410
- - total public activity and likely prospect pool
409
+ and estimated likely prospects. Calculate each row's estimated likely
410
+ prospects from the sampled fit rate when available, otherwise from the stated
411
+ starting estimate; never duplicate public activity or people-to-check counts in
412
+ this column.
413
+ - total public activity, people to check, and likely prospect pool
411
414
  - next step: build the source list, add it to the campaign, and review the
412
415
  first 15 leads before scaling
413
416
  - fallback: switch to active LinkedIn profiles if the first sample is too noisy
@@ -252,9 +252,10 @@ After `import_leads`, poll `wait_for_lead_list_ready` until ready, failed, or
252
252
  cancelled. Rows appearing is not enough for `confirm_lead_list`; use
253
253
  `allowPartialSourceList: true` only when the user explicitly asks to continue early.
254
254
 
255
- For LinkedIn engagement, the Start Import approval uses `## Source
256
- Recommendation`, plain language, selected posts, people to check, likely
257
- prospects, cleanup risk, fallback, and the first 15-lead review.
255
+ For LinkedIn engagement, Start Import uses `## Source Recommendation`: selected
256
+ posts, people to check, likely prospects, cleanup risk, fallback, first 15-lead
257
+ review. Tables show public activity + est. likely prospects, not duplicate
258
+ people-to-check; rows = fit rate * checkable people.
258
259
 
259
260
  A source recommendation must show source path, filters/recipe, raw volume,
260
261
  sample size, sampled fits as n/N plus percentage/range, estimated usable
@@ -267,6 +267,10 @@ For LinkedIn engagement, the second gate is not "approve source" in the abstract
267
267
  It is a concrete scrape approval: show a compact `## Source Recommendation`
268
268
  with the ~300 likely-prospect goal, people-to-check count, selected-post table,
269
269
  total public activity, likely prospect pool, first-review checkpoint, and fallback.
270
+ In the selected-post table, show public activity beside estimated likely
271
+ prospects. Do not duplicate the people-to-check/raw public-activity number in the
272
+ second numeric column; calculate row-level likely prospects from sampled fit rate
273
+ when available or the stated starting estimate.
270
274
  Keep the 10% planning floor as plain "at least 10% of the first sample should
271
275
  look like real prospects." The approval question should be
272
276
  "Approve scraping N recommended LinkedIn posts?" where N comes from the