@sellable/mcp 0.1.149 → 0.1.151

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +8 -4
  2. package/agents/post-find-leads-message-scout.md +2 -2
  3. package/agents/source-scout-prospeo-contact.md +12 -5
  4. package/agents/source-scout-sales-nav.md +13 -3
  5. package/dist/tools/leads.d.ts +2 -1
  6. package/dist/tools/leads.js +162 -15
  7. package/dist/tools/prompts.d.ts +1 -0
  8. package/dist/tools/prompts.js +4 -3
  9. package/dist/tools/registry.d.ts +9 -1
  10. package/dist/tools/rows.d.ts +1 -0
  11. package/dist/tools/rows.js +2 -0
  12. package/dist/tools/rubrics.d.ts +55 -23
  13. package/dist/tools/rubrics.js +95 -10
  14. package/package.json +1 -1
  15. package/skills/create-campaign/SKILL.md +57 -29
  16. package/skills/create-campaign/core/providers/apollo.json +4 -2
  17. package/skills/create-campaign/core/providers/prospeo.json +3 -2
  18. package/skills/create-campaign/references/provider-selection-strategy.md +66 -25
  19. package/skills/create-campaign-v2/SKILL.md +67 -37
  20. package/skills/create-campaign-v2/SOUL.md +11 -7
  21. package/skills/create-campaign-v2/core/flow.v2.json +70 -47
  22. package/skills/create-campaign-v2/references/approval-gate-framing.md +7 -8
  23. package/skills/create-campaign-v2/references/sample-validation-loop.md +9 -5
  24. package/skills/create-campaign-v2/references/step-13-import-leads.md +10 -4
  25. package/skills/create-campaign-v2/references/step-15-re-cascade.md +12 -7
  26. package/skills/create-campaign-v2/references/watch-guide-narration.md +16 -13
  27. package/skills/create-campaign-v2-tail/SKILL.md +24 -16
  28. package/skills/providers/apollo.md +8 -1
  29. package/skills/providers/prospeo.md +11 -1
  30. package/skills/providers/sales-nav.md +1 -1
  31. package/skills/research/config.json +9 -0
  32. package/skills/create-campaign-v2/references/message-review-safety-gate.md +0 -162
@@ -53,7 +53,29 @@ Activity Filters (use one or both):
53
53
 
54
54
  Sales Nav works without these filters too -- just expect lower reply rates.
55
55
 
56
- ### 3. Apollo (LAST RESORT FOR VOLUME)
56
+ ### 3. Prospeo (HIRING / ACCOUNT / VERIFIED-CONTACT EXPANSION)
57
+
58
+ Prospeo is the main lane when the user's direction points to database filters
59
+ that LinkedIn sources do not expose.
60
+
61
+ USE WHEN:
62
+
63
+ - Hiring-led targeting: companies actively hiring specific roles
64
+ - Named-account or domain-list targeting
65
+ - Broad persona expansion where verified contact coverage matters
66
+ - You need `company_job_posting_hiring_for`,
67
+ `company_job_posting_quantity`, funding, headcount, or domain filters
68
+
69
+ SKIP WHEN:
70
+
71
+ - The campaign is mainly about fresh LinkedIn activity or engagement warmth
72
+ - Signal Discovery can clearly produce enough ICP-fit engagers
73
+
74
+ WHY: Prospeo is the only current provider with company job-posting filters by
75
+ role. Sales Nav is stronger for recent LinkedIn activity, but not for
76
+ hiring-by-role filtering.
77
+
78
+ ### 4. Apollo (LAST RESORT FOR VOLUME)
57
79
 
58
80
  Large database but leads may not be active on LinkedIn.
59
81
 
@@ -74,25 +96,30 @@ Is your ICP LinkedIn-active (founders, sales, marketing, GTM, engineers)?
74
96
  NO -> Sales Navigator + POSTED_ON_LINKEDIN (4x reply rates)
75
97
  NO -> Sales Navigator (with or without POSTED_ON_LINKEDIN)
76
98
 
99
+ Need hiring-by-role filters? -> Prospeo (has company job-posting filters)
77
100
  Need tech stack targeting? -> Apollo (has technology filters)
78
- Have specific company names? -> Sales Navigator or Apollo with domains
101
+ Have specific company names/domains? -> Sales Navigator for small lists or Prospeo with domainFilterId
79
102
  ```
80
103
 
81
104
  ## ICP-to-Provider Quick Reference
82
105
 
83
- | ICP Type | Recommended | Why |
84
- | ------------------------- | ---------------- | ---------------------------------------------------- |
85
- | Founders, CEOs | Signal Discovery | Highly active on LinkedIn, lots of founder content |
86
- | Sales/GTM leaders | Signal Discovery | Very active, tons of sales content |
87
- | Marketing leaders | Signal Discovery | Active, lots of marketing content |
88
- | Engineers/DevOps | Signal Discovery | Active on tech discussions, open source |
89
- | Enterprise CTOs | Sales Navigator | Less public engagement, use POSTED_ON_LINKEDIN |
90
- | Procurement/Ops | Sales Navigator | Rarely engage publicly |
91
- | Few specific companies | Sales Navigator | Use CURRENT_COMPANY filter (lookup each company) |
92
- | Company domain list (ABM) | Apollo | Has `q_organization_domains_list` for bulk targeting |
93
- | Tech stack users | Apollo | Has technology filters |
94
-
95
- **Default:** Try Signal Discovery first. Fall back to Sales Navigator if ICP is too niche.
106
+ | ICP Type | Recommended | Why |
107
+ | ------------------------- | ---------------- | -------------------------------------------------- |
108
+ | Founders, CEOs | Signal Discovery | Highly active on LinkedIn, lots of founder content |
109
+ | Sales/GTM leaders | Signal Discovery | Very active, tons of sales content |
110
+ | Marketing leaders | Signal Discovery | Active, lots of marketing content |
111
+ | Engineers/DevOps | Signal Discovery | Active on tech discussions, open source |
112
+ | Enterprise CTOs | Sales Navigator | Less public engagement, use POSTED_ON_LINKEDIN |
113
+ | Procurement/Ops | Sales Navigator | Rarely engage publicly |
114
+ | Few specific companies | Sales Navigator | Use CURRENT_COMPANY filter (lookup each company) |
115
+ | Hiring-led targeting | Prospeo | Has company job-posting filters by role |
116
+ | Company domain list (ABM) | Prospeo | Uses `domainFilterId` for domain targeting |
117
+ | Tech stack users | Apollo | Has technology filters |
118
+
119
+ **Default:** Try Signal Discovery first only when there is no stronger source
120
+ direction and the ICP is plausibly active in public LinkedIn conversations. Fall
121
+ back to Sales Navigator if ICP is too niche. Use Prospeo first when the ask is
122
+ hiring-led, account/domain-led, or broad verified-contact expansion.
96
123
 
97
124
  ## ABM / Account-Based Targeting
98
125
 
@@ -103,10 +130,10 @@ When user has a list of target companies:
103
130
  - Requires looking up each company individually
104
131
  - Can combine with POSTED_ON_LINKEDIN for active users
105
132
 
106
- - **Many companies (domain list):** Use Apollo with `q_organization_domains_list`
107
- - Supports bulk domain upload (up to 190 per search)
108
- - Example: `filters: { q_organization_domains_list: ["stripe.com", "notion.so", "figma.com"] }`
109
- - Trade-off: No POSTED_ON_LINKEDIN equivalent, so reply rates may be lower
133
+ - **Many companies (domain list):** Use Prospeo with `domainFilterId`
134
+ - Supports large domain filters through `load_csv_domains` or `save_domain_filters`
135
+ - Example: create a domain filter for `stripe.com`, `notion.so`, and `figma.com`, then pass `domainFilterId` into `search_prospeo`
136
+ - Trade-off: No POSTED_ON_LINKEDIN equivalent, so LinkedIn activity warmth may be lower
110
137
 
111
138
  ## Recommendation Templates
112
139
 
@@ -141,6 +168,19 @@ Here's why:
141
168
  Should I search for active {icp} on Sales Navigator?
142
169
  ```
143
170
 
171
+ **Prospeo (hiring-led ICP):**
172
+
173
+ ```
174
+ Since this campaign depends on companies actively hiring for **{roleThemes}**, I'd recommend **Prospeo** first.
175
+
176
+ Here's why:
177
+ - Prospeo can filter companies by open-role themes using job-posting filters
178
+ - We can pair those hiring signals with founder, GTM, recruiting, or revenue-owner contacts
179
+ - Sales Nav is useful for LinkedIn activity and referrals, but it cannot filter companies by hiring role
180
+
181
+ Should I search Prospeo for companies hiring {roleThemes} and the right hiring-owner contacts?
182
+ ```
183
+
144
184
  **Apollo (tech stack targeting):**
145
185
 
146
186
  ```
@@ -154,17 +194,17 @@ Here's why:
154
194
  Should I search Apollo for {techStack} users?
155
195
  ```
156
196
 
157
- **Apollo ABM (company domains):**
197
+ **Prospeo ABM (company domains):**
158
198
 
159
199
  ```
160
- Since you have a **list of target companies**, I'd recommend **Apollo** with domain targeting.
200
+ Since you have a **list of target company domains**, I'd recommend **Prospeo** with a domain filter.
161
201
 
162
202
  Here's why:
163
- - Apollo supports bulk domain lists (up to 190 companies per search)
203
+ - Prospeo is the campaign-default path for supplied company-domain lists
204
+ - We'll create a `domainFilterId` from the CSV or pasted domains before searching
164
205
  - We can find decision-makers at your exact target accounts
165
- - Just share the domains (e.g., stripe.com, notion.so) and I'll find your ICP at those companies
166
206
 
167
- Note: Reply rates may be lower than Signal Discovery or Sales Nav with POSTED_ON_LINKEDIN, since we can't filter for LinkedIn activity. Consider combining with a strong personalized message.
207
+ Note: LinkedIn activity warmth may be lower than Signal Discovery or Sales Nav with POSTED_ON_LINKEDIN, so we should inspect the first review batch before scaling.
168
208
 
169
209
  Can you share your target company domains?
170
210
  ```
@@ -179,7 +219,8 @@ Do not hardcode provider options. Build them from the framework:
179
219
  - If user already has some other list shape that does not fit those CSV paths -> proceed with provider selection
180
220
  - If the user specifies a provider or research plan -> treat that as a hard override
181
221
  - Else if `providerPreference` override exists -> recommend that provider
182
- - Else use the decision hierarchy above (Signal Discovery -> Sales Nav -> Apollo)
222
+ - Else use the decision hierarchy above only when there is no stronger source
223
+ direction (Signal Discovery -> Sales Nav -> Prospeo -> Apollo)
183
224
  2. Build options from `providerOrder` and `framework.providers[providerId].askOption`
184
225
  3. Mark the recommended option by appending " (Recommended)" if needed
185
226
 
@@ -49,9 +49,10 @@ for debug output.
49
49
  12. Sync the approved template into the campaign brief.
50
50
  13. After message approval, keep the watched app on Filter Leads while the
51
51
  bounded enrichment/filter cascade starts.
52
- 14. Move to Messages only after at least one review row passes, generate and
53
- review bounded messages, then hand off to Settings, sender, sequence, and
54
- explicit launch greenlight.
52
+ 14. Move to Messages only after at least one review row passes and one generated
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.
55
56
 
56
57
  There is no normal approval-packet, commit-gate, atomic-mint, or local
57
58
  artifact-validation step. Those belong only to legacy validation/rehearsal
@@ -125,6 +126,16 @@ Default source order when the user has not supplied a source:
125
126
  3. broader Sales Nav role/title filters
126
127
  4. Prospeo account/contact expansion
127
128
 
129
+ Use that order only when the brief has no stronger sourcing constraint. If the
130
+ campaign is hiring-led, asks for companies actively hiring specific roles, asks
131
+ for open-role/job-posting signals, or needs verified contacts at companies with
132
+ those hiring signals, start with Prospeo. Prospeo supports
133
+ `company_job_posting_hiring_for` and `company_job_posting_quantity`; Sales Nav
134
+ does not provide hiring-by-role filters. For those campaigns, Signal Discovery
135
+ can be a conversation-signal check if relevant hiring posts are likely, and
136
+ Sales Nav is a LinkedIn activity/referral fallback rather than the main hiring
137
+ filter.
138
+
128
139
  Before any provider prompt, search, source scout, or signal-discovery call,
129
140
  show a short source-plan gate and ask for approval. This first approval
130
141
  authorizes source scouting/search only. The gate must say, in plain language:
@@ -161,14 +172,30 @@ the target engager/source-candidate volume, the bounded campaign review-batch
161
172
  size, the cleanup risk, and the fallback if the selected posts look wrong. The
162
173
  approval label must describe the action with the count, such as "Approve
163
174
  scraping 3 Signal Discovery posts?" For Sales Nav or Prospeo, the label should
164
- name the specific search/import lane. Do not call `import_leads` or
165
- `confirm_lead_list` until this second source-action approval is granted.
175
+ name the specific search/import lane and source lead count. Do not call
176
+ `import_leads` or `confirm_lead_list` until this second source-action approval
177
+ is granted.
178
+
179
+ For Sales Nav and Prospeo, do not ask to import only the 25-row review batch at
180
+ the source-action gate. First-page samples are for source math: compute sampled
181
+ fit after conservative cleanup, project how many good-fit prospects the raw
182
+ pool can yield, and keep refining filters while the projected good-fit pool is
183
+ below the campaign target (normally about 150+ usable prospects unless the
184
+ campaign/source defaults say otherwise). Once the lane clears the target, ask
185
+ approval to materialize the source list with
186
+ `targetLeadCount = min(rawResultCount, providerMax, ceil(targetGoodFitLeads /
187
+ projectedFitRateAfterCleanup))`. After that source list is ready,
188
+ `confirm_lead_list` imports only the bounded review batch into the campaign
189
+ table for fit and message review.
190
+
166
191
  After the user approves this concrete source-action gate, do not show the
167
192
  Source Recommendation again and do not ask another source approval question.
168
193
  Acknowledge once, then call `import_leads` immediately with the approved source
169
- math. For Signal Discovery, pass `provider: "signal-discovery"`,
170
- `targetEngagerCount`, `maxPostsToScrape`, and `confirmed: true`; the tool owns
171
- moving the watch UI to source-list progress after a lead-list/job id exists.
194
+ math. For Sales Nav/Prospeo, pass `targetLeadCount` as the approved source-list
195
+ export count, not the review-batch size. For Signal Discovery, pass
196
+ `provider: "signal-discovery"`, `targetEngagerCount`, `maxPostsToScrape`, and
197
+ `confirmed: true`; the tool owns moving the watch UI to source-list progress
198
+ after a lead-list/job id exists.
172
199
 
173
200
  For Signal Discovery, use this compact source-action approval shape after
174
201
  selected posts exist:
@@ -181,7 +208,7 @@ Use Signal Discovery first.
181
208
  **Good-fit target:** ~150 prospects after cleanup, enrichment, and filters<br>
182
209
  **Source-candidate plan:** scrape ~1,000 raw engagers using a conservative 15% fit-rate assumption<br>
183
210
  **Planning floor:** continue only when sampled/projected fit is at least 10% after cleanup; below that, switch to Sales Nav recent activity<br>
184
- **Review checkpoint:** import the first 25 leads into the campaign for fit and message review before scaling<br>
211
+ **Review checkpoint:** after the source list exists, clone only the bounded review batch into the campaign for fit and message review<br>
185
212
 
186
213
  ### Selected posts
187
214
 
@@ -202,8 +229,9 @@ This gives enough volume to work toward ~150 good-fit prospects, while
202
229
  keeping the source tied to people already engaging with Claude Code outbound /
203
230
  AI-native sales workflows.
204
231
 
205
- **First pass:** build the source list, then import only the 25-lead review
206
- batch so we can inspect fit and messages before scaling.
232
+ **First pass:** build the source list at the approved source-candidate target,
233
+ then clone only the bounded review batch into the campaign so we can inspect
234
+ fit and messages before sending.
207
235
 
208
236
  **Fallback:** if sampled/projected fit falls below 10%, or if the review batch
209
237
  is too vendor-heavy, agency-heavy, or off-ICP, switch to Sales Nav recent
@@ -213,7 +241,11 @@ activity.
213
241
  A source recommendation must show concrete evidence: source lane, filters or
214
242
  recipe, raw volume, sample size, sampled fits as n/N plus percentage/range,
215
243
  estimated usable prospects, cleanup risk, runner-up, and what approval
216
- authorizes.
244
+ authorizes. For Sales Nav/Prospeo it must also show source export math:
245
+ `rawResultCount`, `sampledFitRate`, conservative projected fit rate,
246
+ `targetLeadCount` for the source list, and projected good-fit count from that
247
+ export. If projected good-fit count is below target, the recommendation is to
248
+ refine or broaden filters, not to import a 25-row batch.
217
249
 
218
250
  Supplied profile CSVs, company/domain CSVs, pasted domains, and existing
219
251
  Sellable lead lists are supported, but keep provider mechanics out of the first
@@ -222,46 +254,45 @@ customer-facing source-choice labels.
222
254
  ## Post-Lead Workstreams
223
255
 
224
256
  After `confirm_lead_list` imports a non-empty bounded review batch and
225
- `get_rows_minimal({ tableId: workflowTableId })` proves rows exist, call
226
- `get_post_find_leads_scout_registry` and start the Message Draft Builder branch
227
- immediately when the current host exposes that returned agent. Do this before
228
- asking the filter-choice question. If no real background branch can start, say
229
- the real sequence and do not claim background drafting is running.
230
-
231
- The message branch uses live CampaignOffer/source/table state as the source of
232
- truth and may draft while the user is choosing filters. It does not write
233
- message cells, enrich rows, attach sequences, or unlock Settings. The Lead Fit
234
- Builder branch starts only after the user chooses filters. Debug markdown/json
235
- artifacts are optional only.
257
+ `get_rows_minimal({ tableId: workflowTableId })` proves rows exist, ask the
258
+ filter-choice question immediately. Do not call
259
+ `get_post_find_leads_scout_registry`, load filter/message subskill prompts, or
260
+ spawn post-lead workers before that question. The only customer-facing work
261
+ before the question should be a short review-batch summary and the choice:
262
+ add filters, skip filters, or revise source.
263
+
264
+ If the user chooses filters, then load the post-lead registry/reference needed
265
+ for filtering and start the Lead Fit Builder. Also start the Message Draft
266
+ Builder in the background from the same campaign/table basis as soon as the
267
+ filter-choice answer is known. If the user skips filters, move the watched app to
268
+ Messages and run the Message Draft Builder there. Debug markdown/json artifacts
269
+ are optional only.
236
270
 
237
271
  When the user chooses filters, immediately call
238
272
  `update_campaign({ campaignId, enableICPFilters: true, currentStep: "create-icp-rubric", watchNarration })`
239
273
  before rubric thinking or branch work. The watched app should move to Filter
240
274
  Rules quickly. After `save_rubrics`, the watched app should move to
241
275
  `apply-icp-rubric` / Filter Leads so the user can see the saved filters are
242
- ready before message approval unlocks any enrichment or filtering.
276
+ ready and wait there for the background message agent. Tell the user explicitly
277
+ that a message agent is drafting the first-message template while enrichment,
278
+ filtering, and Generate Message cells remain blocked.
243
279
 
244
280
  Lead Fit Builder persists production rubrics with `save_rubrics` when filters
245
281
  are enabled. It must not require `brief.md`, `lead-review.md`, or
246
282
  `lead-sample.json`.
247
283
 
248
- Message Draft Builder is `post-find-leads-message-scout`. It must load the full
249
- message prompt:
284
+ Run `post-find-leads-message-scout` as the background Message Draft Builder
285
+ whenever the host exposes it. It must load:
250
286
 
251
287
  ```text
252
288
  get_subskill_prompt({ subskillName: "generate-messages", offset, limit }) until hasMore=false
253
289
  ```
254
290
 
255
- It may also load the supplemental approval checklist:
256
-
257
- ```text
258
- get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-safety-gate.md" })
259
- ```
260
-
261
- Do not load the full `generate-messages` prompt in the create-campaign parent
262
- thread unless you are executing the parent-thread fallback for the actual
263
- message-draft branch. Parent-thread template approval uses only the compact
264
- message-review safety gate.
291
+ No shortcut message instructions are valid. If the host cannot launch the
292
+ agent, the parent fallback must run the same full prompt from live campaign
293
+ state before drafting. Do not render message review until
294
+ `messageDraftRecommendation` proves current campaign/table/review-batch
295
+ `generate-messages` basis.
265
296
 
266
297
  ## Hard Gates
267
298
 
@@ -284,7 +315,6 @@ Load references only when needed:
284
315
  - `references/watch-guide-narration.md` for watched-step narration.
285
316
  - `references/lead-validation-preview.md` for legacy/debug preview shapes.
286
317
  - `references/filter-leads.md` for rubric design and `save_rubrics` rules.
287
- - `references/message-review-safety-gate.md` for final message approval checks.
288
318
  - `references/step-13-import-leads.md` before review-batch import.
289
319
  - `references/sample-validation-loop.md` before review-batch validation.
290
320
  - `references/final-handoff-contract.md` for Settings, sender, sequence, and
@@ -274,14 +274,18 @@ keep the output numeric but do not claim the source scout was parallel or
274
274
  surface install status to the customer.
275
275
 
276
276
  For post-lead work, call `get_post_find_leads_scout_registry` after
277
+ the user chooses filters, not before the filter-choice question. After
277
278
  `confirm_lead_list` imports a non-empty bounded review batch and
278
- `get_rows_minimal` proves rows exist. Start `post-find-leads-message-scout`
279
- immediately when real subagents are available, before asking the filter-choice
280
- question. Start `post-find-leads-filter-scout` only after the user chooses
281
- filters. This is the same registry pattern as source scouting, but the trigger
282
- for message drafting is review-batch import, not filter approval. The join gate
283
- is live branch readiness: saved rubrics or a resolved skip-filter choice, plus a
284
- message recommendation grounded in the same campaign/table basis.
279
+ `get_rows_minimal` proves rows exist, ask add-filters vs skip-filters
280
+ immediately. Once the user answers, start `post-find-leads-message-scout` /
281
+ message generation from the same campaign/table basis. If the user chooses
282
+ filters, also start `post-find-leads-filter-scout`, move the browser to Filter
283
+ Rules, save rubrics, then keep the browser on Filter Leads while the message
284
+ recommendation is reviewed. If the user skips filters, move the browser to
285
+ Messages/message review. The join gate is live branch readiness: saved rubrics
286
+ or a resolved skip-filter choice, plus a message recommendation grounded in the
287
+ same campaign/table basis. Enrichment, filtering, and product Generate Message
288
+ cells still wait for template approval.
285
289
 
286
290
  Only promise parallel post-lead work when parallel work actually started. If the
287
291
  host cannot or should not launch background branches, say the real sequence:
@@ -66,9 +66,7 @@
66
66
  "filter": [
67
67
  "references/filter-leads.md"
68
68
  ],
69
- "message": [
70
- "references/message-review-safety-gate.md"
71
- ],
69
+ "message": [],
72
70
  "tail": [
73
71
  "references/sample-validation-loop.md",
74
72
  "references/step-15-re-cascade.md",
@@ -588,20 +586,9 @@
588
586
  ]
589
587
  },
590
588
  {
591
- "action": "launch_message_draft_builder_after_review_batch_import",
592
- "tool": "get_post_find_leads_scout_registry",
593
- "target": "post-find-leads-message-scout",
594
- "requiresNonEmptyRows": true,
595
- "mustRunBefore": [
596
- "filter-choice question",
597
- "filter approval",
598
- "save_rubrics"
599
- ],
600
- "mode": "background_when_host_supports_subagents",
601
- "fallback": "if no real background branch can start, say the real sequence and do not claim background drafting is running",
602
- "toolCallRequiredInBranch": "get_subskill_prompt({ subskillName: \"generate-messages\", offset, limit }) until hasMore=false",
603
- "runtimeProofTransport": "CampaignOffer.watchNarration.workerDetails.messageDraftBuilder",
604
- "purpose": "start the provisional message draft from the imported review batch immediately; do not defer this to filter approval"
589
+ "action": "summarize_review_batch_and_advance_to_filter_choice",
590
+ "purpose": "ask filter choice immediately; no post-lead registries, filter refs, or message prompts first",
591
+ "maxCustomerCopyLines": 4
605
592
  }
606
593
  ],
607
594
  "requiredCampaignState": [
@@ -611,8 +598,6 @@
611
598
  ],
612
599
  "allowedTools": [
613
600
  "get_subskill_prompt",
614
- "get_subskill_asset",
615
- "get_post_find_leads_scout_registry",
616
601
  "import_leads",
617
602
  "wait_for_lead_list_ready",
618
603
  "confirm_lead_list",
@@ -620,16 +605,18 @@
620
605
  "get_rows_minimal",
621
606
  "update_campaign",
622
607
  "AskUserQuestion",
623
- "request_user_input",
624
- "Task",
625
- "spawn_agent"
608
+ "request_user_input"
626
609
  ],
627
610
  "doNotAllow": [
611
+ "get_post_find_leads_scout_registry",
612
+ "Task",
613
+ "spawn_agent",
628
614
  "list_senders",
629
615
  "queue_cells",
630
616
  "start_campaign",
631
617
  "enrich_with_prospeo",
632
- "bulk_enrich_with_prospeo"
618
+ "bulk_enrich_with_prospeo",
619
+ "save_rubrics"
633
620
  ],
634
621
  "waitFor": "review_batch_imported",
635
622
  "transitions": {
@@ -659,6 +646,13 @@
659
646
  ]
660
647
  }
661
648
  ],
649
+ "hardRules": [
650
+ "ask_filter_choice_immediately_after_review_batch_import",
651
+ "do_not_call_get_subskill_prompt_before_filter_choice",
652
+ "do_not_call_get_subskill_asset_before_filter_choice",
653
+ "do_not_call_get_post_find_leads_scout_registry_before_filter_choice",
654
+ "do_not_spawn_post_lead_agents_before_filter_choice"
655
+ ],
662
656
  "requiredCampaignState": [
663
657
  "campaignId",
664
658
  "campaignBrief",
@@ -672,6 +666,11 @@
672
666
  "get_campaign_navigation_state"
673
667
  ],
674
668
  "doNotAllow": [
669
+ "get_subskill_prompt",
670
+ "get_subskill_asset",
671
+ "get_post_find_leads_scout_registry",
672
+ "Task",
673
+ "spawn_agent",
675
674
  "create_campaign",
676
675
  "list_senders",
677
676
  "import_leads",
@@ -693,7 +692,7 @@
693
692
  },
694
693
  {
695
694
  "id": "post-lead-workstreams",
696
- "label": "Filter and message workstreams",
695
+ "label": "Filter workstream",
697
696
  "onEnter": [
698
697
  {
699
698
  "action": "persist_add_filters_approval",
@@ -715,17 +714,18 @@
715
714
  },
716
715
  "mustRunBefore": [
717
716
  "get_post_find_leads_scout_registry",
718
- "launch_or_reuse_post_lead_workstreams",
717
+ "launch_lead_fit_builder_after_filter_choice",
719
718
  "save_rubrics"
720
719
  ]
721
720
  },
722
721
  {
723
722
  "tool": "get_post_find_leads_scout_registry",
724
- "purpose": "load canonical post-lead worker names"
723
+ "purpose": "load canonical post-lead worker names only after the user has chosen filters"
725
724
  },
726
725
  {
727
- "action": "launch_or_reuse_lead_fit_builder_and_existing_message_draft",
726
+ "action": "launch_lead_fit_builder_after_filter_choice",
728
727
  "mode": "parallel_when_host_supports_subagents",
728
+ "target": "post-find-leads-filter-scout",
729
729
  "inputs": [
730
730
  "campaignId",
731
731
  "campaignBrief",
@@ -734,9 +734,16 @@
734
734
  "reviewBatchRowIds/hash",
735
735
  "filterChoice"
736
736
  ],
737
- "stateSource": "CampaignOffer and workflow table rows",
738
- "debugFilesOptionalOnly": true,
739
- "messageDraftRule": "reuse or join the Message Draft Builder branch that started immediately after confirm_lead_list; do not start first-time message drafting here unless the earlier branch failed to start"
737
+ "stateSource": "live campaign/table",
738
+ "debugFilesOptionalOnly": true
739
+ },
740
+ {
741
+ "action": "launch_message_draft_builder_after_filter_decision",
742
+ "mode": "parallel_when_host_supports_subagents",
743
+ "target": "post-find-leads-message-scout",
744
+ "when": "filters_enabled",
745
+ "doesNotQueueCells": true,
746
+ "customerNarration": "Say message agent is drafting."
740
747
  },
741
748
  {
742
749
  "action": "save_filter_rubrics_to_campaign",
@@ -793,10 +800,13 @@
793
800
  "hardRules": [
794
801
  "after_save_rubrics_currentStep_must_be_apply-icp-rubric",
795
802
  "do_not_move_browser_to_messages_until_filter_leads_step_is_current_or_filters_are_explicitly_skipped",
796
- "message_draft_builder_start_is_not_deferred_until_filters"
803
+ "no_post_lead_worker_or_deep_prompt_before_filter_choice",
804
+ "lead_fit_builder_starts_only_after_filters_enabled",
805
+ "msg_draft_after_filter_choice",
806
+ "msg_draft_no_cells"
797
807
  ],
798
808
  "transitions": {
799
- "post_lead_workstreams_ready": "message-review",
809
+ "post_lead_workstreams_ready": "message-generation",
800
810
  "revise_leads": "find-leads",
801
811
  "revise_rubric": "filter-rubric",
802
812
  "revise_messaging": "message-generation",
@@ -865,14 +875,23 @@
865
875
  "id": "message-generation",
866
876
  "label": "Message generation",
867
877
  "onEnter": [
878
+ {
879
+ "action": "set_message_review_visible_step_by_filter_choice",
880
+ "tool": "update_campaign",
881
+ "branchRules": [
882
+ "yes: currentStep=apply-icp-rubric; wait on Filter Leads",
883
+ "no: currentStep=messages; message review"
884
+ ],
885
+ "watchNarration.stage": "fit-message"
886
+ },
868
887
  {
869
888
  "action": "run_or_reconcile_message_draft_builder",
870
889
  "target": "post-find-leads-message-scout",
871
890
  "toolCallRequiredBeforeDraft": [
872
- "get_subskill_prompt({ subskillName: \"generate-messages\", offset, limit }) until hasMore=false",
873
- "for approval-only parent-thread review, use get_subskill_asset({ subskillName: \"create-campaign-v2\", assetPath: \"references/message-review-safety-gate.md\" }) instead of loading generate-messages"
891
+ "run background post-find-leads-message-scout when available",
892
+ "get_subskill_prompt({ subskillName: \"generate-messages\", offset, limit }) until hasMore=false"
874
893
  ],
875
- "stateSource": "campaignBrief, selected source state, selectedLeadListId, workflowTableId, bounded review-batch row ids/hash",
894
+ "stateSource": "campaignBrief, source, selectedLeadListId, workflowTableId, review-batch row ids/hash",
876
895
  "outputState": "messageDraftRecommendation"
877
896
  }
878
897
  ],
@@ -884,16 +903,16 @@
884
903
  ],
885
904
  "allowedTools": [
886
905
  "get_subskill_prompt",
887
- "get_subskill_asset",
888
906
  "get_campaign",
889
907
  "get_rows_minimal",
908
+ "update_campaign",
890
909
  "AskUserQuestion",
891
910
  "request_user_input"
892
911
  ],
893
912
  "toolRules": [
894
- "Before message drafting, the Message Draft Builder branch loads the full get_subskill_prompt({ subskillName: \"generate-messages\" }) prompt and drafts from campaignBrief, selected source state, selectedLeadListId, workflowTableId, and imported review-batch rows. For approval-only parent-thread template review, load references/message-review-safety-gate.md and do not load the full generate-messages prompt.",
913
+ "Message Draft Builder must run as the background post-find-leads-message-scout when the host exposes it. If the host cannot launch the agent, the parent-thread fallback must execute the same full get_subskill_prompt({ subskillName: \"generate-messages\" }) from live state before drafting.",
895
914
  "Do not use brief.md, lead-review.md, or lead-sample.json as required live state; those files are optional debug context only.",
896
- "The compact messageDraftRecommendation must return templateRecommendation, tokenFillRules, renderedSample, concerns, status, basisToken, outputAt, outputHash, and error or retry detail.",
915
+ "The messageDraftRecommendation must return templateRecommendation, tokenFillRules, renderedSample, concerns, status, basisToken, outputAt, outputHash, and error or retry detail.",
897
916
  "If campaign/source/table/review-batch basis does not match, classify the output stale or blocked."
898
917
  ],
899
918
  "doNotAllow": [
@@ -902,7 +921,6 @@
902
921
  "save_rubrics",
903
922
  "import_leads",
904
923
  "confirm_lead_list",
905
- "update_campaign",
906
924
  "queue_cells",
907
925
  "start_campaign",
908
926
  "generate_messages"
@@ -984,7 +1002,6 @@
984
1002
  "allowedTools": [
985
1003
  "AskUserQuestion",
986
1004
  "request_user_input",
987
- "get_subskill_asset",
988
1005
  "update_campaign_brief",
989
1006
  "update_campaign",
990
1007
  "get_rows_minimal",
@@ -1124,8 +1141,14 @@
1124
1141
  "cellSource": "pending_generate_message_cells_for_passing_rows using approved_campaign_brief_template"
1125
1142
  },
1126
1143
  {
1127
- "tool": "wait_for_campaign_table_ready",
1128
- "purpose": "wait_for_generate_message_cells_to_complete"
1144
+ "tool": "wait_for_rubric_results",
1145
+ "purpose": "wait_for_first_passing_generated_message",
1146
+ "requiredValues": {
1147
+ "includeRows": false,
1148
+ "minPassedCount": 1,
1149
+ "minMessagesCount": 1
1150
+ },
1151
+ "readVia": "stats_only_tool_result"
1129
1152
  },
1130
1153
  {
1131
1154
  "action": "observe_generate_message_results",
@@ -1169,25 +1192,24 @@
1169
1192
  "currentStep": "auto-execute-messaging",
1170
1193
  "watchNarration.stage": "review-ready"
1171
1194
  },
1172
- "watchNarrationRule": "Say what just happened, that review-batch messages are ready in Messages, and that the next action is reviewing or approving generated messages before Settings."
1195
+ "watchNarrationRule": "Say the first passing generated message is ready in Messages; next is review before Settings."
1173
1196
  },
1174
1197
  {
1175
1198
  "action": "ask_generated_message_review_choice",
1176
1199
  "uses": "request_user_input",
1177
1200
  "choices": [
1178
- "Approve generated messages",
1201
+ "Approve generated message and continue to Settings",
1179
1202
  "Revise filters",
1180
1203
  "Revise message template",
1181
1204
  "Pause here"
1182
- ],
1183
- "rule": "Do not advance to Settings until the generated review-batch messages have been reviewed and approved."
1205
+ ]
1184
1206
  }
1185
1207
  ],
1186
1208
  "allowedTools": [
1187
1209
  "get_subskill_asset",
1188
1210
  "get_rows_minimal",
1189
1211
  "queue_cells",
1190
- "wait_for_campaign_table_ready",
1212
+ "wait_for_rubric_results",
1191
1213
  "update_campaign",
1192
1214
  "AskUserQuestion",
1193
1215
  "request_user_input"
@@ -1201,6 +1223,7 @@
1201
1223
  "hardRules": [
1202
1224
  "critique_failure_never_escalates",
1203
1225
  "critique_sample_size_bounded_by_config",
1226
+ "first_passing_generated_message_unblocks_review",
1204
1227
  "critics_fixed_at_targeting_copy_voice",
1205
1228
  "synthesis_enforces_phase_84_token_contract",
1206
1229
  "opus_reserved_for_highest_value_subset",