@sellable/mcp 0.1.149 → 0.1.150

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.
@@ -4,15 +4,16 @@ This reference governs Step 15 (`auto-execute-messaging`) re-cascade
4
4
  behavior when Step 14's validate-sample loop graduates additional rows
5
5
  from pending → passed after the first Generate Message cells have already run.
6
6
 
7
- Load whenever Step 15 is about to transition to
8
- `awaiting-user-greenlight`, and on every resume into Step 15.
7
+ Load whenever Step 15 is about to ask for generated-message review or transition
8
+ to `awaiting-user-greenlight`, and on every resume into Step 15.
9
9
 
10
10
  ## Principle
11
11
 
12
- Generate Message cells are cascade-scoped. If Step 14's rubric flips rows
13
- from pending → passed AFTER Step 15 first observes messages for the review
14
- batch, the new rows can sit pending with no message. Step 15 must explicitly
15
- queue the newly-pending Generate Message cells for the review-batch subset.
12
+ Generate Message cells are cascade-scoped. If Step 14's rubric flips rows from
13
+ pending → passed AFTER Step 15 first observes messages for the review batch, the
14
+ new rows can sit pending with no message. That must not block the first review
15
+ handoff. Step 15 opens review as soon as one passing generated message exists;
16
+ late-passed rows can be re-cascaded after explicit user continuation or resume.
16
17
 
17
18
  Observed on manual Phase-85 signal-discovery run (2026-04-20): 15 new
18
19
  rows graduated pending → passed mid-tail while `messagesCount` stayed
@@ -22,13 +23,17 @@ flat at 257. The new rows never got messages.
22
23
 
23
24
  Re-cascade runs whenever ALL of the following are true:
24
25
 
25
- 1. Step 15 has already observed the initial review-batch message cascade.
26
+ 1. The user has already approved the first generated message or explicitly asked
27
+ to continue processing more review-batch rows.
26
28
  2. A subsequent check of rubric state shows rows that were pending at
27
29
  first message-generation pass are now passed.
28
30
  3. Those newly-passed rows do NOT yet have generated messages
29
31
  (`messagesCount` flat relative to pre-cascade).
30
32
  4. Step 15 has NOT yet transitioned to `awaiting-user-greenlight`.
31
33
 
34
+ Before that first generated-message approval, do not run this loop just to wait
35
+ for a bigger sample. One passing generated message is enough for review.
36
+
32
37
  If condition 4 already fired (i.e. we're in Step 16), the re-cascade
33
38
  runs on resume into Step 15 if validate-sample was re-entered and new
34
39
  rows graduated.
@@ -194,10 +194,10 @@ After review batch import:
194
194
  ```json
195
195
  {
196
196
  "stage": "fit-message",
197
- "headline": "I recommend adding filters",
198
- "visibleState": "The first review batch is in the campaign. The visible sample looks mixed enough that filters should be added before message review.",
199
- "agentIntent": "Codex is asking whether you want to further filter these leads before message review. Skip filters only if the visible rows already look clean.",
200
- "nextAction": "Choose filters or skip",
197
+ "headline": "Filtering may not be needed",
198
+ "visibleState": "25 review leads are in the campaign table from 181 source candidates. Sample read: 23/25 look like senior target-role fits; 2 need cleanup or manual review. The browser is showing the filter-choice screen.",
199
+ "agentIntent": "Codex is not recommending filters because the sample already looks clean. Fit examples: Dave Kranowitz (Chief Revenue Officer); Marie Didominica (Head of Growth Marketing). Add filters only for a narrow exclusion.",
200
+ "nextAction": "Skip filters or add a narrow cleanup rule",
201
201
  "workerStatuses": {
202
202
  "leadFitBuilder": "idle",
203
203
  "messageDraftBuilder": "running"
@@ -206,11 +206,13 @@ After review batch import:
206
206
  ```
207
207
 
208
208
  Use this after the selected review rows are present and before filters are
209
- saved. This is add-filters intent, not active filtering. Recommend adding
210
- filters when the sample is mixed/noisy, tell the user to Choose filters or skip,
211
- and do not say filtering the batch before rubrics and message approval are
212
- saved. The Message Draft Builder should start immediately after the bounded
213
- review batch exists; mark it running only when that branch actually started.
209
+ saved. The filter recommendation must be row-specific: say why filters are
210
+ recommended from the sample counts and examples, or say filtering may not be
211
+ needed when the visible review rows already look clean. This is a user decision
212
+ gate, not active filtering; do not say filtering the batch before rubrics and
213
+ message approval are saved. The Message Draft Builder should start immediately
214
+ after the bounded review batch exists; mark it running only when that branch
215
+ actually started.
214
216
  When the user chooses filters, immediately persist `enableICPFilters: true` and
215
217
  move to `create-icp-rubric` so the watched app shows Filter Rules while Codex
216
218
  defines the rules in chat. After `save_rubrics`, move to `apply-icp-rubric`
@@ -252,16 +254,17 @@ Template approved, bounded filter test running:
252
254
  "stage": "fit-message",
253
255
  "headline": "Template saved",
254
256
  "visibleState": "The browser stays on Filter Leads while the bounded enrichment and filter test runs.",
255
- "agentIntent": "Codex saved the approved message template, queued the review-batch Enrich Prospect cells, and is waiting for at least one row to pass before moving to Messages.",
256
- "nextAction": "Move to Messages after a passing row"
257
+ "agentIntent": "Codex saved the approved message template, queued the review-batch Enrich Prospect cells, and is waiting for one passing row with one generated message before moving to review.",
258
+ "nextAction": "Review the first passing generated message"
257
259
  }
258
260
  ```
259
261
 
260
262
  Do not move to Messages immediately after `approve-message`. The visible route
261
263
  is already Filter Leads after `save_rubrics`; approving the message only unlocks
262
264
  the bounded cascade from that screen. Move to Messages only once at least one
263
- review-batch row passes and Generate Message cells are ready/running for the
264
- passing rows.
265
+ review-batch row passes and one generated message is ready for review. Do not
266
+ wait for the rest of the review batch or a stronger sample before asking the
267
+ user to approve the generated message.
265
268
 
266
269
  Messages waiting for template:
267
270
 
@@ -58,11 +58,12 @@ Step 14 — kick bounded cascade + observe sample
58
58
  passing filtered row exists.)
59
59
 
60
60
  Step 15 — observe messaging
61
- get_rows_minimal # confirm passing rows have completed Generate Message cells
61
+ wait_for_rubric_results({ minPassedCount: 1, minMessagesCount: 1, includeRows: false })
62
+ get_rows_minimal # confirm the first passing generated message exists
62
63
  (rare) queue_cells on any pending Generate Message cells
63
64
  token-contract spot check via get_rows
64
65
  update_campaign(currentStep=auto-execute-messaging) with review-ready narration
65
- ask the user to approve generated review-batch messages before Settings
66
+ ask the user to approve the generated message before Settings
66
67
  only after approval: update_campaign(currentStep=awaiting-user-greenlight)
67
68
  (generate_messages is NOT an MCP tool; messages come from the cascade)
68
69
 
@@ -291,8 +292,10 @@ Do not route to a visible `validate-sample` step. Full decision tree lives in
291
292
  review batch only. After `save_rubrics` and the approved message template are
292
293
  persisted, Step 14 queues the review-batch Enrich Prospect cells, waits until
293
294
  filter results start landing, then moves to message observation as soon as one
294
- row passes. It does NOT call `check_rubric`, `bulk_enrich_with_prospeo`, or any
295
- other direct enrichment/scoring tool.
295
+ row passes. Step 15 opens review as soon as one passing generated message
296
+ exists. Do not wait for a larger or stronger sample once that first passing
297
+ message is ready. It does NOT call `check_rubric`,
298
+ `bulk_enrich_with_prospeo`, or any other direct enrichment/scoring tool.
296
299
 
297
300
  Shape:
298
301
 
@@ -307,6 +310,7 @@ projectedPass = round(passInSample / sampleSize * importLimit)
307
310
  if wait_for_rubric_results.ready === true and passRate.passed >= 1:
308
311
  advance to Step 15 to observe or queue Generate Message for currently passing rows
309
312
  do not wait for every sample row to finish before message generation starts
313
+ stop for review as soon as one passing generated message is ready
310
314
  else if wait_for_rubric_results.ready === false and reason === "timeout":
311
315
  use the partial passRate/stats as the sample diagnostic
312
316
  if passRate.passed >= 1:
@@ -382,17 +386,20 @@ Template`. If it does not, fail before the cascade runs. Do not repair
382
386
  already (cascade auto-fired it). If it is still `pending`, queue
383
387
  it explicitly: `queue_cells({ tableId, cellIds:
384
388
  <generateMessageCellIds> })`.
385
- 3. `wait_for_campaign_table_ready` (or poll) until every passing
386
- row's Generate Message cell is `completed`.
387
- 4. Read the results back via `get_rows` (full) and sanity-check a
388
- sample against the Phase 84 token contract: no unresolved
389
+ 3. `wait_for_rubric_results({ tableId, targetCount: reviewBatchSize,
390
+ minPassedCount: 1, minMessagesCount: 1, includeRows: false })` until the
391
+ first passing generated message is ready. Do not wait for every passing row's
392
+ Generate Message cell, and do not add "one more wait" for a stronger sample.
393
+ Remaining review-batch rows can continue processing in the background.
394
+ 4. Read the first ready generated message back via `get_rows` (full) and
395
+ sanity-check that sample against the Phase 84 token contract: no unresolved
389
396
  `{{tokens}}`, no invented proof, one sentence per line, etc.
390
397
  5. If the sample fails the token contract, diagnose brief-vs-list
391
398
  (same revision loop as Step 14) and escalate if over
392
399
  `maxRevisionRounds`.
393
- 6. On success, keep `currentStep: "auto-execute-messaging"` and ask the user
394
- to approve the generated review-batch messages. Only that approval may move
395
- the campaign to Settings / `awaiting-user-greenlight`.
400
+ 6. On success, keep `currentStep: "auto-execute-messaging"` and ask the user to
401
+ approve the generated message before continuing to Settings. Only that
402
+ approval may move the campaign to Settings / `awaiting-user-greenlight`.
396
403
 
397
404
  **Do NOT hand-write message bodies via `update_cell`.** `update_cell`
398
405
  is reachable for legitimate operator overrides AFTER the tail hands
@@ -432,15 +439,16 @@ strings, which is why Step 16 requires Step 15 to be complete.
432
439
  4. Check `messaging.tokenContract`. When `strict`, reject any sample
433
440
  message that contains unresolved or unsupported tokens (including
434
441
  any critique rewrite that tried to introduce one).
435
- 5. If the sample passes the token contract (and critique when enabled),
436
- stop at the review-batch handoff. Do NOT scale to the full source list
437
- before explicit user expansion approval.
442
+ 5. If the first passing generated message passes the token contract (and
443
+ critique when enabled), stop at the review-batch handoff. Do NOT wait for the
444
+ remaining review-batch rows and do NOT scale to the full source list before
445
+ explicit user expansion approval.
438
446
  6. If the sample fails the token contract or critique, diagnose +
439
447
  loop the same way Step 14 does (brief-vs-list), subject to the same
440
448
  `maxRevisionRounds` cap.
441
449
  7. On success, keep `currentStep: "auto-execute-messaging"`, show that the
442
- review-batch messages are ready in Messages, and ask for approval before
443
- Settings. Only after the user approves those generated messages should
450
+ first passing generated message is ready in Messages, and ask for approval
451
+ before Settings. Only after the user approves the generated message should
444
452
  `update_campaign({ campaignId, currentStep: "awaiting-user-greenlight" })`
445
453
  run.
446
454
 
@@ -378,7 +378,14 @@ search_apollo({
378
378
 
379
379
  ### ABM / Domain List Targeting
380
380
 
381
- For account-based targeting, use `q_organization_domains_list` to search specific companies:
381
+ For campaign routing, supplied company-domain lists should go to Prospeo first
382
+ using `load_csv_domains` or `save_domain_filters`, then `domainFilterId`.
383
+ Apollo still supports `q_organization_domains_list` as a secondary/legacy
384
+ capability when the user explicitly chooses Apollo or needs an Apollo-only
385
+ filter such as a technographic constraint.
386
+
387
+ If Apollo is explicitly selected for account-based targeting, use
388
+ `q_organization_domains_list` to search specific companies:
382
389
 
383
390
  ```json
384
391
  search_apollo({
@@ -62,7 +62,7 @@ search_prospeo({
62
62
  - Pass `searchId` on subsequent pages to paginate.
63
63
  - Use `import_leads` with `provider: \"prospeo\"` and the `searchId` to create a lead list and start import.
64
64
  - **IMPORTANT:** If `import_leads` returns `needsModeSelection: true`, use `AskUserQuestion` to ask "add to existing leads or replace?" Do NOT assume.
65
- - Default source target is 300+ good-fit leads, capped at 2,500 source candidates for now.
65
+ - Default source target is about 150 good-fit leads, capped at 2,500 source candidates for now.
66
66
  - Apply the campaign source planning floor: the sampled/projected good-fit rate
67
67
  after cleanup should be at least 10%. Prospeo is the terminal fallback; if the
68
68
  best reasonable Prospeo lane is still below 10%, tighten the ICP/source
@@ -95,6 +95,11 @@ Prospeo filters are split into person vs company. Most filters use `include` / `
95
95
 
96
96
  Preference rules:
97
97
 
98
+ - For hiring-led campaigns, use `company_job_posting_hiring_for` to target the
99
+ open-role themes and `company_job_posting_quantity` when the campaign needs
100
+ an active hiring floor. Pair those company hiring filters with buyer/referrer
101
+ person filters such as founders, GTM leaders, talent leaders, or revenue
102
+ owners.
98
103
  - For ABM lists, use `load_csv_domains` + `domainFilterId` when the accounts are already in a CSV file on disk.
99
104
  - For pasted/raw domain lists, use `save_domain_filters` + `domainFilterId` instead of inline domains or `company.websites.include`.
100
105
  - If user input starts as company names, resolve names to domains first, then use `save_domain_filters`.
@@ -167,6 +172,11 @@ search_prospeo({
167
172
 
168
173
  ## When to Use Prospeo
169
174
 
175
+ - **Hiring-led targeting**: Find companies hiring for specific roles with
176
+ `company_job_posting_hiring_for` and `company_job_posting_quantity`, then
177
+ identify reachable buyer/referrer contacts at those companies
178
+ - **Account/domain targeting**: Use `domainFilterId` from `load_csv_domains` or
179
+ `save_domain_filters` for ABM searches
170
180
  - **Email Finding**: Get verified work emails from LinkedIn URLs
171
181
  - **Lead Enrichment**: Add company data, job history, and contact info to leads
172
182
  - **Bulk Operations**: Enrich up to 100 leads at once
@@ -387,7 +387,7 @@ User: "Save it"
387
387
  <limits>
388
388
  - 25 results per page
389
389
  - Maximum 100 pages (2,500 leads)
390
- - Default source target: 300+ good-fit leads, capped at 2,500 source
390
+ - Default source target: about 150 good-fit leads, capped at 2,500 source
391
391
  candidates for now
392
392
  - Maximum 5 search calls per session
393
393
  - If user needs more than 2,500: explain limit, suggest splitting by region
@@ -0,0 +1,9 @@
1
+ {
2
+ "parallelMode": "wide",
3
+ "agentCount": 6,
4
+ "maxToolCallsPerAgent": 2,
5
+ "senderMaxAgents": 2,
6
+ "senderMaxToolCallsPerAgent": 3,
7
+ "progressMode": true,
8
+ "debugMode": true
9
+ }