@sellable/mcp 0.1.103 → 0.1.105

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.
@@ -7,10 +7,10 @@ Required first step:
7
7
  - Load the canonical provider prompt before searching. If the parent supplies a
8
8
  draft `campaignOfferId`, call `get_provider_prompt({ provider:
9
9
  "signal-discovery", campaignOfferId, confirmed: true })` and include that same
10
- `campaignOfferId` in `search_signals` so the user can watch source work in the
11
- campaign UI. Treat that as a campaign-attached persisted search; do not run a
12
- post-mint search without the campaign ID. If no campaign ID is supplied, run
13
- campaignless preview mode.
10
+ `campaignOfferId` plus `currentStep: "signal-discovery"` in `search_signals`
11
+ so the user can watch source work in the campaign UI. Treat that as a
12
+ campaign-attached persisted search; do not run a post-mint search without the
13
+ campaign ID. If no campaign ID is supplied, run campaignless preview mode.
14
14
 
15
15
  Use the inherited Sellable MCP tools when available:
16
16
 
@@ -6,9 +6,10 @@ Required first step:
6
6
 
7
7
  - Load the canonical provider prompt before searching. If the parent supplies a
8
8
  draft `campaignOfferId`, call `get_provider_prompt({ provider: "prospeo",
9
- campaignOfferId, confirmed: true })` and include that same `campaignOfferId` in
10
- `search_prospeo` so the user can watch source work in the campaign UI. If no
11
- campaign ID is supplied, run campaignless preview mode. Treat post-mint
9
+ campaignOfferId, confirmed: true })` and include that same `campaignOfferId`
10
+ plus `currentStep: "prospeo"` in `search_prospeo` so the user can watch source
11
+ work in the campaign UI. If no campaign ID is supplied, run campaignless
12
+ preview mode. Treat post-mint
12
13
  searches with `campaignOfferId` as campaign-attached persisted search tabs;
13
14
  do not run a live campaign search without the campaign ID.
14
15
 
@@ -7,8 +7,9 @@ Required first step:
7
7
  - Load the canonical provider prompt before searching. If the parent supplies a
8
8
  draft `campaignOfferId`, call `get_provider_prompt({ provider: "sales-nav",
9
9
  campaignOfferId, confirmed: true })` and include that same `campaignOfferId` in
10
- `search_sales_nav` so the user can watch source work in the campaign UI. If no
11
- campaign ID is supplied, run campaignless preview mode. Treat post-mint
10
+ `search_sales_nav` with `currentStep: "sales-nav"` so the user can watch
11
+ source work in the campaign UI. If no campaign ID is supplied, run
12
+ campaignless preview mode. Treat post-mint
12
13
  searches with `campaignOfferId` as campaign-attached persisted search tabs;
13
14
  do not run a live campaign search without the campaign ID.
14
15
 
@@ -594,7 +594,7 @@ export const leadToolDefinitions = [
594
594
  },
595
595
  {
596
596
  name: "search_sales_nav",
597
- description: 'Search LinkedIn Sales Navigator. Requires get_provider_prompt({ provider: "sales-nav" }) first. Returns normalized results with pagination. `campaignOfferId` is optional for directional preview runs; include it only when the search should be associated with a campaign.',
597
+ description: 'Search LinkedIn Sales Navigator. Requires get_provider_prompt({ provider: "sales-nav" }) first. Returns normalized results with pagination. `campaignOfferId` is optional for directional preview runs; include it only when the search should be associated with a campaign. Post-mint create-campaign-v2 watch runs MUST pass campaignOfferId and currentStep: "sales-nav" so the search appears in the watched campaign UI. Omitting campaignOfferId post-mint orphans the search from the UI.',
598
598
  inputSchema: {
599
599
  type: "object",
600
600
  properties: {
@@ -739,7 +739,7 @@ export const leadToolDefinitions = [
739
739
  },
740
740
  {
741
741
  name: "search_prospeo",
742
- description: 'Search Prospeo for people using filters and optional domainFilterId. Requires get_provider_prompt({ provider: "prospeo" }) first. When targeting known accounts, call load_csv_domains for CSV-on-disk workflows or save_domain_filters for pasted/raw domain lists, then pass domainFilterId. Raw domain inputs and company-name targeting are NOT supported in this MCP tool. Strategy: start with 2-3 high-signal filters (title/seniority + industry or domainFilterId + headcount), then tighten one filter at a time. For security, AppSec, SOC, RevOps, Demand Gen, and similar function-specific lanes, do not widen with bare seniority labels like "Head" or "Director" alone; pair them with explicit function-title keywords and inspect the sample for off-function `Head of X` leakage. Prefer person location over company HQ unless HQ is explicitly needed. `campaignOfferId` routing rule: OMIT campaignOfferId ONLY in pre-mint Phase 84 `find leads` discovery mode (validating ICP before the commit gate). In every other context — post-mint lead additions, operator-driven searches on a live campaign, any search where the intent is to persist results to a specific campaign — you MUST pass campaignOfferId so the search shows up in that campaign\'s Contact Search panel. Omitting campaignOfferId post-mint orphans the search from the UI. Returns normalized results with pagination.',
742
+ description: 'Search Prospeo for people using filters and optional domainFilterId. Requires get_provider_prompt({ provider: "prospeo" }) first. When targeting known accounts, call load_csv_domains for CSV-on-disk workflows or save_domain_filters for pasted/raw domain lists, then pass domainFilterId. Raw domain inputs and company-name targeting are NOT supported in this MCP tool. Strategy: start with 2-3 high-signal filters (title/seniority + industry or domainFilterId + headcount), then tighten one filter at a time. For security, AppSec, SOC, RevOps, Demand Gen, and similar function-specific lanes, do not widen with bare seniority labels like "Head" or "Director" alone; pair them with explicit function-title keywords and inspect the sample for off-function `Head of X` leakage. Prefer person location over company HQ unless HQ is explicitly needed. `campaignOfferId` routing rule: OMIT campaignOfferId ONLY in pre-mint Phase 84 `find leads` discovery mode (validating ICP before the commit gate). In every other context — post-mint lead additions, operator-driven searches on a live campaign, any search where the intent is to persist results to a specific campaign — you MUST pass campaignOfferId so the search shows up in that campaign\'s Contact Search panel. Post-mint create-campaign-v2 watch runs MUST pass currentStep: "prospeo". Omitting campaignOfferId post-mint orphans the search from the UI. Returns normalized results with pagination.',
743
743
  inputSchema: {
744
744
  type: "object",
745
745
  properties: {
@@ -848,7 +848,7 @@ export const leadToolDefinitions = [
848
848
  },
849
849
  {
850
850
  name: "search_signals",
851
- description: 'Search LinkedIn posts for signal discovery. Requires get_provider_prompt({ provider: "signal-discovery" }) first. Supports keyword search, profile posts, company posts, or a single post URL. Use campaignless preview mode for directional discovery; include `campaignOfferId` only when the search should persist into campaign state. Returns a compact summary with recommended posts to avoid context bloat.',
851
+ description: 'Search LinkedIn posts for signal discovery. Requires get_provider_prompt({ provider: "signal-discovery" }) first. Supports keyword search, profile posts, company posts, or a single post URL. Use campaignless preview mode for directional discovery; include `campaignOfferId` when the search should persist into campaign state. Post-mint create-campaign-v2 watch runs MUST pass campaignOfferId and currentStep: "signal-discovery" so the search appears in the watched campaign UI. Omitting campaignOfferId post-mint orphans the search from the UI. Returns a compact summary with recommended posts to avoid context bloat.',
852
852
  inputSchema: {
853
853
  type: "object",
854
854
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.103",
3
+ "version": "0.1.105",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: create-campaign-v2
3
- description: Execute the JSON-gated shell-first campaign flow with chained Phase 84 artifacts: create a watchable campaign shell with a v1 brief, attach the source with campaignId, import the first 10-row review batch, save rubrics and approved message template, then queue the review cascade and hand off to settings/sequence/start.
3
+ description: Execute the JSON-gated shell-first campaign flow with chained Phase 84 artifacts: create a watchable campaign shell with a v1 brief, attach the source with campaignId, import the first 15-row review batch, save rubrics and approved message template, then queue the review cascade and hand off to settings/sequence/start.
4
4
  visibility: internal
5
5
  ---
6
6
 
@@ -11,7 +11,7 @@ You are the create-campaign-v2 orchestrator. Your job is to execute the
11
11
  configured `core/flow.v2.json` state machine from scratch: (1) interview the
12
12
  user, resolve campaign identity/client-prospect context, and create a watchable
13
13
  campaign shell with the v1 brief already attached, (2) use that campaign id for
14
- source selection, (3) import/confirm the first 10-row review batch to establish
14
+ source selection, (3) import/confirm the first 15-row review batch to establish
15
15
  `workflowTableId`, (4) create rubrics and message artifacts from that campaign
16
16
  table sample, (5) sync the approved message set into the campaign brief, and
17
17
  (6) queue/observe the bounded cascade before settings, sequence, and start.
@@ -23,12 +23,12 @@ Run the configured JSON flow in durable stages:
23
23
  0. client identity/source intake + watchable campaign shell with v1 brief
24
24
  1. create-campaign-brief
25
25
  2. find leads with the campaign id
26
- 3. import/confirm the first 10-row review batch
26
+ 3. import/confirm the first 15-row review batch
27
27
  4. filter leads from the campaign table sample
28
28
  5. generate message from the same campaign table sample
29
29
  6. message review gate
30
30
  7. sync approved message set into the campaign brief
31
- 8. queue and validate the 10-row cascade
31
+ 8. queue and validate the 15-row cascade
32
32
  9. settings/sender, sequence, and start handoff
33
33
 
34
34
  The JSON flow is the source of truth for stage order, artifact policy,
@@ -94,9 +94,9 @@ Optional debug/UAT draft directory, disabled in normal customer runs:
94
94
  stage, call `update_campaign({ campaignId, currentStep })` with the visible UI
95
95
  step the user should be watching, then continue the work from MCP/product
96
96
  state. Use `create-offer` for the brief, `pick-provider` or the selected
97
- provider step while sourcing, `filter-choice` after the 10-row review batch is
97
+ provider step while sourcing, `filter-choice` after the 15-row review batch is
98
98
  imported, `messages`/`auto-execute-messaging` for message work,
99
- `validate-sample` for the 10-row validation cascade, and
99
+ `validate-sample` for the 15-row validation cascade, and
100
100
  `awaiting-user-greenlight` for Settings. Do not advance `currentStep` backward.
101
101
  - After the shell is minted, normal resume paths read the CampaignOffer first.
102
102
  Use debug files to explain or reconstruct work, not to decide whether a
@@ -172,7 +172,7 @@ Optional debug/UAT draft directory, disabled in normal customer runs:
172
172
  "Sellable token".
173
173
  "Quick question panel" is only acceptable when explaining a Codex/Claude setup
174
174
  blocker.
175
- - Before the 10-lead import/test batch, do not call `check_rubric`; Phase 84
175
+ - Before the 15-lead import/test batch, do not call `check_rubric`; Phase 84
176
176
  only writes and validates artifacts, saves rubrics, and syncs campaign setup
177
177
  state.
178
178
  - Never narrate local draft housekeeping to the user. If you create directories,
@@ -201,7 +201,7 @@ Optional debug/UAT draft directory, disabled in normal customer runs:
201
201
  - Do not call `list_senders`, `get_sender`, or surface connected/missing sender
202
202
  state during setup, brief, source, filter, or message review. Sender
203
203
  availability belongs only to the Settings/final launch handoff after
204
- `approve-message` and the 10-lead validation sample. The first user-visible
204
+ `approve-message` and the 15-lead validation sample. The first user-visible
205
205
  sender blocker should be at `awaiting-user-greenlight`/Settings.
206
206
  - If the invocation or user answer includes an existing `clientProspectId`, keep
207
207
  it as the preferred `create_campaign` identity input. If it includes a
@@ -432,9 +432,16 @@ to be worth a LinkedIn test. I'll compare source paths by expected volume,
432
432
  sampled ICP fit, activity/warmth signal, cleanup risk, and tradeoffs. This
433
433
  usually takes ~3-5 min, and I'll show you the source decision + sample before
434
434
  anything goes live.`
435
+ - In watch mode, do not leave the user sitting on only `pick-provider` while
436
+ source scouts run. Move the campaign to the likely primary source lane
437
+ (`signal-discovery`, `sales-nav`, or `prospeo`) before background source
438
+ scouts, then run the first campaign-attached provider prompt + provider search
439
+ in the parent thread with `campaignOfferId`, `confirmed: true`, and
440
+ `currentStep` when the tool accepts it. Background scouts may continue after
441
+ the visible campaign tab exists.
435
442
  - After the lead sample/source decision is ready and approved,
436
443
  show the next progress line:
437
- `Lead source is set. I'll import the first 10-row review batch into the
444
+ `Lead source is set. I'll import the first 15-row review batch into the
438
445
  campaign table, then use that same batch to tighten the fit filter and draft the
439
446
  message we should test.`
440
447
  - During long post-intake work, show concise progress checkpoints before the
@@ -509,7 +516,7 @@ message we should test.`
509
516
  and `message-validation.md`, then reconciles that the selected message basis
510
517
  rows still pass the final filter.
511
518
  If a legacy/resume host starts message prep from preview rows before import,
512
- it still needs at least 5 probable good-fit rows and must reconcile the final
519
+ it still needs at least 3 probable good-fit rows and must reconcile the final
513
520
  winner against the imported review batch before message review.
514
521
  - `lead-sample.json` from `find leads` is always the message sample source.
515
522
  `filter leads` must not create a different message sample or cause message
@@ -542,6 +549,11 @@ message we should test.`
542
549
  then draft the message from the same sample.` Never say `kicking off two
543
550
  workstreams`, `in parallel`, or `background` unless parallel branches were
544
551
  actually launched.
552
+ - Source scout parallelism must not hide all provider work from the watch UI.
553
+ The parent thread owns the first visible provider search: call the chosen
554
+ provider prompt/search with the minted CampaignOffer id and provider
555
+ `currentStep` before waiting on source-scout results, so relevant search tabs
556
+ appear in real time.
545
557
  - For post-lead workstreams, first call
546
558
  `get_post_find_leads_scout_registry` and launch exactly the returned
547
559
  `filter-leads` and `message-generation` scouts when real subagents are
@@ -556,7 +568,7 @@ workstreams`, `in parallel`, or `background` unless parallel branches were
556
568
  - Never call a tool outside the active step's `allowedTools`, and never call a
557
569
  tool listed in the active step's `doNotAllow`.
558
570
  - Before the source is approved, `import_leads` and `confirm_lead_list` are
559
- forbidden. After source approval, import/confirm only the bounded 10-row
571
+ forbidden. After source approval, import/confirm only the bounded 15-row
560
572
  review batch. Before rubrics and the approved message set are both on the
561
573
  campaign, the spend/send-adjacent cascade tools are forbidden: `queue_cells`,
562
574
  `enrich_with_prospeo`, `bulk_enrich_with_prospeo`,
@@ -565,7 +577,7 @@ workstreams`, `in parallel`, or `background` unless parallel branches were
565
577
  the active `flow.v2.json` step allows them.
566
578
  - During pre-import validation, do not call `check_rubric`; use the lead-filter
567
579
  artifacts and only use campaign-backed scoring after Step 13 imports the
568
- 10-lead test batch.
580
+ 15-lead test batch.
569
581
  - Resume state is based on CampaignOffer state first, then the presence and
570
582
  completeness of the chained debug artifacts. Never treat file presence as the
571
583
  durable source of truth after the campaign exists.
@@ -574,8 +586,8 @@ workstreams`, `in parallel`, or `background` unless parallel branches were
574
586
  - Exception: brief-validated may rewrite §3 Campaign Thesis AND §12 Next Steps
575
587
  when Phase-84 lead-yield data clearly contradicts a Phase-83 UNVALIDATED
576
588
  decision on primary lead-source. "Clearly contradicts" = the Phase-83
577
- primary source yields 0 FIT while an alternative source yields ≥ 5 FIT in
578
- the same 10-row test sample (or an equivalent ≥ 5× ratio at larger samples).
589
+ primary source yields 0 FIT while an alternative source yields ≥ 3 FIT in
590
+ the same 15-row test sample (or an equivalent ≥ 5× ratio at larger samples).
579
591
  Every rewrite MUST cite specific yield numbers from `lead-review.md`. All
580
592
  other Phase-83 brief sections remain read-only. See
581
593
  `references/filter-leads.md` § Brief-Validated Rewrite Authority for the
@@ -584,14 +596,14 @@ workstreams`, `in parallel`, or `background` unless parallel branches were
584
596
  artifact intact.
585
597
  - If a required upstream artifact is missing, stop and route back to the
586
598
  missing step instead of guessing.
587
- - Before importing the 10-lead test batch, persist a customer-facing
599
+ - Before importing the 15-lead test batch, persist a customer-facing
588
600
  `message-review.md` and `message-review-decision.md` so the message decision
589
601
  can be inspected later.
590
602
  - The message review must show one concrete sample message rendered as the
591
603
  recipient would see it, in addition to the approved message template. Do not
592
604
  make the user mentally expand `{{tokens}}`.
593
605
  - Do not include sequence, cadence, sending-window, mailbox, or campaign
594
- settings review in `message-review.md`. Those come after the 10-lead test
606
+ settings review in `message-review.md`. Those come after the 15-lead test
595
607
  batch, in the settings/sequence handoff.
596
608
  - Do not include post-accept DMs, connection-accepted follow-ups, day-2 / day-7
597
609
  follow-ups, second touches, reply branches, or any other sequence-shaped copy
@@ -620,7 +632,7 @@ There are four customer-visible gates in the net-new hosted flow:
620
632
  only whether to proceed with the selected message (`approve-message`) or run
621
633
  one more messaging revision (`revise-messaging`). `approve-message` authorizes
622
634
  syncing the approved message set into the campaign brief, saving rubrics,
623
- importing the bounded 10-lead test batch, and queueing/observing that sample.
635
+ importing the bounded 15-lead test batch, and queueing/observing that sample.
624
636
  - The sender/settings/sequence handoff is the launch gate. After message
625
637
  validation, use Settings to help the user connect or select a LinkedIn sender.
626
638
  Explain Slack reply review before launch. After sender selection, attach the
@@ -81,7 +81,7 @@ example, like `omit the noticed... line` or `use "operators"`. Missing data
81
81
  should never produce robotic or creepy copy.
82
82
 
83
83
  Approved token guidance is part of the campaign, not just the review. Before
84
- the 10-lead test batch imports, the campaign brief should carry forward the
84
+ the 15-lead test batch imports, the campaign brief should carry forward the
85
85
  token fill rules and examples: good fills, good omits, bad fills, fallback
86
86
  rules, and why the bad fills are blocked.
87
87
  The campaign brief must carry forward the token fill rules from review into the
@@ -33,16 +33,16 @@ the imported review batch for validation).
33
33
 
34
34
  - **`sampleSize`** — How many rows the validation loop pulls from the
35
35
  imported review batch. In v2 this matches the review-batch cap
36
- (default 25), so the user sees enough real rows to judge the campaign
36
+ (default 15), so the user sees enough real rows to judge the campaign
37
37
  without spending credits on hundreds more.
38
38
  - **`minProjectedPass`** — Passing-message floor required before handoff.
39
- The default requires 5 passing examples from the 25-row review batch.
39
+ The default requires 3 passing examples from the 15-row review batch.
40
40
  Math:
41
41
  ```text
42
42
  projectedPass = round(passInSample / sampleSize * importLimit)
43
43
  ```
44
- With defaults (sampleSize=25, importLimit=25), `projectedPass` equals
45
- the actual review-batch pass count. 5 passing rows is exactly at the
44
+ With defaults (sampleSize=15, importLimit=15), `projectedPass` equals
45
+ the actual review-batch pass count. 3 passing rows is exactly at the
46
46
  floor.
47
47
  - **`maxRevisionRounds`** — Hard cap before escalating to the user. A
48
48
  revision round is one full sample pass that triggered brief revision
@@ -130,7 +130,7 @@ logs and adjust:
130
130
  batches and credit spend is acceptable.
131
131
  - `sampleSize` higher if a 25-row review batch is not enough to judge
132
132
  quality for a specific market.
133
- - `minProjectedPass` lower only if fewer than 5 passing examples is still
133
+ - `minProjectedPass` lower only if fewer than 3 passing examples is still
134
134
  enough for a confident user decision.
135
135
  - `maxRevisionRounds` should rarely change; 3 is already generous. If
136
136
  brief revision is hitting the cap often, the brief template upstream
@@ -17,7 +17,7 @@ import:
17
17
  # Initial review batch imported in Step 13 before the sample validation
18
18
  # loop. Import + enrichment must never exceed this cap before the user
19
19
  # reviews the sample and explicitly asks to expand.
20
- importLimit: 10
20
+ importLimit: 15
21
21
  # Provider is inherited from the campaign-attached source association created
22
22
  # during find-leads. Step 13 may re-run provider preflight in memory, but it
23
23
  # does not choose a new source.
@@ -27,11 +27,11 @@ sample:
27
27
  # Rows pulled from the imported cohort for the validation loop. In v2 this
28
28
  # equals the review-batch cap so the user sees a focused first test batch
29
29
  # without spending credits on hundreds of rows.
30
- sampleSize: 10
30
+ sampleSize: 15
31
31
  # Projected first-batch passing count required to proceed to sample
32
32
  # messaging. This is not approval to scale the full source list.
33
33
  # projectedPass = round(passInSample / sampleSize * importLimit).
34
- minProjectedPass: 5
34
+ minProjectedPass: 3
35
35
  # Hard cap on revision loops before escalating to the user. On a stale
36
36
  # resume the counter does NOT reset — the 3-round cap holds across
37
37
  # sessions.
@@ -106,7 +106,7 @@ handoff:
106
106
  # Orientation surfaced in Step 16 ("awaiting-user-greenlight") along with
107
107
  # the watch link. Keep this short and user-facing.
108
108
  orientation: >-
109
- Review the first 10 enriched leads and messages. If they look good,
109
+ Review the first 15 enriched leads and messages. If they look good,
110
110
  attach a sender in Settings, accept the recommended sequence, and start
111
111
  the campaign without spending credits on more leads first.
112
112
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "v2",
3
3
  "workflow": "create-campaign-v2",
4
- "principle": "CampaignOffer state and the watch link are canonical from the first brief onward. Disk artifacts are optional debug/UAT diagnostics, not the normal customer surface. Resume, gating, and handoff read campaign state first. Start from user intake, create a watchable campaign shell with a v1 brief, update currentStep before major visible work, attach source/search state to that CampaignOffer, import the bounded review batch before post-import fit/message scouts, save rubrics and an approved message template, then queue the 10-row cascade and hand off to settings/sequence/start.",
4
+ "principle": "CampaignOffer state and the watch link are canonical from the first brief onward. Disk artifacts are optional debug/UAT diagnostics, not the normal customer surface. Resume, gating, and handoff read campaign state first. Start from user intake, create a watchable campaign shell with a v1 brief, update currentStep before major visible work, attach source/search state to that CampaignOffer, import the bounded review batch before post-import fit/message scouts, save rubrics and an approved message template, then queue the 15-row cascade and hand off to settings/sequence/start.",
5
5
  "artifactPolicy": {
6
6
  "normalCustomerPath": "Use CampaignOffer state, MCP responses, provider search state, and campaign table rows. Do not create, read, link, or surface local draft files unless debug/UAT mode is explicit or the user asks for them.",
7
7
  "debugArtifactsAreOptional": true,
@@ -520,6 +520,33 @@
520
520
  "when": "before_source_scouts_or_provider_search",
521
521
  "chatRenderRule": "Move the campaign watch view to Find Contacts before the main thread starts comparing source paths. Do not mention MCP or local artifacts."
522
522
  },
523
+ {
524
+ "action": "advance_watch_to_initial_source_lane",
525
+ "tool": "update_campaign",
526
+ "requiredFields": [
527
+ "campaignId",
528
+ "currentStep"
529
+ ],
530
+ "currentStepByPrimaryLane": {
531
+ "signals": "signal-discovery",
532
+ "salesNav": "sales-nav",
533
+ "prospeo": "prospeo",
534
+ "apollo": "apollo-ai",
535
+ "existingList": "saved-lists",
536
+ "uploadedDomains": "prospeo"
537
+ },
538
+ "when": "before_background_source_scouts",
539
+ "rule": "Choose the likely primary visible source lane from source intake, brief preference, or the best first lane the main thread will actually search. Do this before waiting on background scouts so watch mode never sits on only Pick Provider while source work happens elsewhere."
540
+ },
541
+ {
542
+ "action": "run_first_campaign_attached_source_search",
543
+ "requiredFields": [
544
+ "campaignOfferId",
545
+ "currentStep"
546
+ ],
547
+ "before": "waiting_on_background_source_scouts",
548
+ "rule": "Before relying on background source scouts, the parent thread must run the first provider prompt + provider search for the chosen visible lane with campaignOfferId and currentStep (signal-discovery, sales-nav, or prospeo) so the campaign UI creates the corresponding live search/tab. Background scouts may continue after that, but the user must see at least one relevant campaign-attached search begin in the watched page."
549
+ },
523
550
  {
524
551
  "action": "render_find_leads_progress",
525
552
  "requiredVisibleContent": [
@@ -555,7 +582,7 @@
555
582
  "action": "run_subskill",
556
583
  "target": "find-leads",
557
584
  "mode": "campaign-attached-required",
558
- "sourceScoutRule": "Shell-first flow requires the CampaignOffer campaignId from durable state. Pass campaignId as campaignOfferId into every provider prompt/search that can persist source state (`get_provider_prompt({ provider, campaignOfferId, confirmed: true })`, `search_signals`, `search_sales_nav`, `search_prospeo`) so the user can watch the selected source inside the campaign. The later import_leads call must use the same campaignOfferId. When several source lanes are credible, scout them independently, then write one primary source recommendation and any runner-up tradeoffs. Do not import, confirm, enrich, queue, or start leads during source discovery."
585
+ "sourceScoutRule": "Shell-first flow requires the CampaignOffer campaignId from durable state. Pass campaignId as campaignOfferId into every provider prompt/search that can persist source state (`get_provider_prompt({ provider, campaignOfferId, confirmed: true })`, `search_signals`, `search_sales_nav`, `search_prospeo`) and include currentStep for tools that accept it so the user can watch the selected source inside the campaign. In watch mode, run the first campaign-attached provider search in the parent thread before waiting on background scouts; subagents can explore runner-up lanes after the visible campaign tab exists. The later import_leads call must use the same campaignOfferId. When several source lanes are credible, scout them independently, then write one primary source recommendation and any runner-up tradeoffs. Do not import, confirm, enrich, queue, or start leads during source discovery."
559
586
  },
560
587
  {
561
588
  "action": "optional_debug_artifacts",
@@ -725,11 +752,11 @@
725
752
  "approved brief and real sample leads",
726
753
  "no import or enrichment until rubrics and message set are ready",
727
754
  "parallel only if real parallel branches were launched",
728
- "import the first 10-row review batch before fit/message work",
755
+ "import the first 15-row review batch before fit/message work",
729
756
  "selectedLeadListId stays the source list and workflowTableId is the campaign table"
730
757
  ],
731
758
  "timeEstimate": "~2-3 min",
732
- "chatRenderRule": "Lead source is set. Next import and confirm only the first 10-row review batch into the campaign table. After workflowTableId exists, run the fit-filter and message-generation workstreams from the campaign table sample. If real parallel MCP/tool branches or host subagents were actually launched, say so; otherwise say the branches will run sequentially. Never claim parallelism unless parallel execution actually started."
759
+ "chatRenderRule": "Lead source is set. Next import and confirm only the first 15-row review batch into the campaign table. After workflowTableId exists, run the fit-filter and message-generation workstreams from the campaign table sample. If real parallel MCP/tool branches or host subagents were actually launched, say so; otherwise say the branches will run sequentially. Never claim parallelism unless parallel execution actually started."
733
760
  },
734
761
  {
735
762
  "action": "ask_continue_revise_or_confirm_only_if_needed",
@@ -808,7 +835,7 @@
808
835
  },
809
836
  {
810
837
  "id": "auto-execute-leads",
811
- "label": "Step 13: Confirm source and import 10 lead review batch",
838
+ "label": "Step 13: Confirm source and import 15 lead review batch",
812
839
  "currentStepValue": "confirm-lead-list",
813
840
  "reference": "references/step-13-import-leads.md",
814
841
  "onEnter": [
@@ -848,7 +875,7 @@
848
875
  "campaignOfferId",
849
876
  "targetLeadCount"
850
877
  ],
851
- "targetLeadCountFromConfig": "import.importLimit (10)",
878
+ "targetLeadCountFromConfig": "import.importLimit (15)",
852
879
  "onZeroLeads": "escalate_hard_fail",
853
880
  "modeAddHandshake": {
854
881
  "firstCallReturns": "needsModeSelection=true + existingLeadListId",
@@ -872,7 +899,7 @@
872
899
  },
873
900
  {
874
901
  "tool": "confirm_lead_list",
875
- "targetLeadCountFromConfig": "import.importLimit (10)",
902
+ "targetLeadCountFromConfig": "import.importLimit (15)",
876
903
  "sourceBranches": [
877
904
  "normal-discovery",
878
905
  "supplied-domains",
@@ -896,7 +923,7 @@
896
923
  "tool": "get_rows_minimal",
897
924
  "purpose": "read_imported_review_batch_from_workflowTableId",
898
925
  "stripCarryData": true,
899
- "sampleSizeFromConfig": "sample.sampleSize (10)"
926
+ "sampleSizeFromConfig": "sample.sampleSize (15)"
900
927
  },
901
928
  {
902
929
  "tool": "update_campaign",
@@ -999,7 +1026,7 @@
999
1026
  "ownership": "proof inventory, token strategy, angle drafting, skeptical-prospect review, and selected winner only"
1000
1027
  }
1001
1028
  ],
1002
- "earlyMessageStartRule": "After auto-execute-leads confirms the 10-row review batch and workflowTableId is ready, launch message-generation from brief.md, lead-review.md, lead-sample.json, and the imported campaign table sample. The message worker carries the campaign-launch message rules in its agent prompt; parent-thread fallback loads references/message-review-safety-gate.md. Legacy/resume preview prep still requires at least 5 probable good-fit rows. It may run beside filter-leads, but the cascade cannot queue until save_rubrics and update_campaign_brief both succeed.",
1029
+ "earlyMessageStartRule": "After auto-execute-leads confirms the 15-row review batch and workflowTableId is ready, launch message-generation from brief.md, lead-review.md, lead-sample.json, and the imported campaign table sample. The message worker carries the campaign-launch message rules in its agent prompt; parent-thread fallback loads references/message-review-safety-gate.md. Legacy/resume preview prep still requires at least 3 probable good-fit rows. It may run beside filter-leads, but the cascade cannot queue until save_rubrics and update_campaign_brief both succeed.",
1003
1030
  "finalMessageReconcileRule": "message-validation.md may start before lead-filter.md exists, but before message-review it must cite only imported review-batch rows that still pass lead-filter.md. If the selected winner depends on a row later excluded by lead-filter.md, revise message-generation before message review.",
1004
1031
  "claudeRule": "In Claude Code, launch both returned post-find-leads scouts with Task/Agent subagents in the same assistant message only when the current session lists those agent names. Do not run filter first and then message generation unless subagents/background work are unavailable.",
1005
1032
  "codexRule": "In Codex, launch both returned post-find-leads scout names as disjoint subagents in the same assistant turn only when the host exposes those custom agents for this run. If the host cannot spawn them, run the same branches sequentially and say so.",
@@ -1879,7 +1906,7 @@
1879
1906
  },
1880
1907
  {
1881
1908
  "id": "validate-sample",
1882
- "label": "Step 14: Validate 10-lead test batch",
1909
+ "label": "Step 14: Validate 15-lead test batch",
1883
1910
  "currentStepValue": "validate-sample",
1884
1911
  "reference": "references/sample-validation-loop.md",
1885
1912
  "counter": {
@@ -1895,13 +1922,13 @@
1895
1922
  },
1896
1923
  {
1897
1924
  "tool": "queue_cells",
1898
- "cellSource": "ten_lead_review_batch_after_rubrics_and_message_set",
1899
- "batchSize": 10,
1925
+ "cellSource": "fifteen_lead_review_batch_after_rubrics_and_message_set",
1926
+ "batchSize": 15,
1900
1927
  "requiredBeforeCall": [
1901
1928
  "rubrics_saved_to_campaign",
1902
1929
  "message_set_synced_to_brief"
1903
1930
  ],
1904
- "note": "Queue only the 10-lead review batch after rubrics are saved and the approved message set is in campaignBrief. This starts the workflow-table cascade for DNC Check -> ICP Score -> Passes Rubric -> Generate Message."
1931
+ "note": "Queue only the 15-lead review batch after rubrics are saved and the approved message set is in campaignBrief. This starts the workflow-table cascade for DNC Check -> ICP Score -> Passes Rubric -> Generate Message."
1905
1932
  },
1906
1933
  {
1907
1934
  "tool": "wait_for_campaign_table_ready",
@@ -1911,7 +1938,7 @@
1911
1938
  "tool": "get_rows_minimal",
1912
1939
  "purpose": "read_passes_rubric_and_generate_message_status",
1913
1940
  "stripCarryData": true,
1914
- "sampleSizeFromConfig": "sample.sampleSize (10)"
1941
+ "sampleSizeFromConfig": "sample.sampleSize (15)"
1915
1942
  },
1916
1943
  {
1917
1944
  "tool": "wait_for_rubric_results",
@@ -1922,7 +1949,7 @@
1922
1949
  "requiredValues": {
1923
1950
  "includeRows": false
1924
1951
  },
1925
- "note": "The shell-first flow tests 10 leads first; always pass cohortSize explicitly instead of relying on default 25 behavior.",
1952
+ "note": "The shell-first flow tests 15 leads first; always pass cohortSize explicitly instead of relying on default 25 behavior.",
1926
1953
  "readVia": "stats_only_tool_result",
1927
1954
  "extractFields": [
1928
1955
  "ready",
@@ -2009,7 +2036,7 @@
2009
2036
  },
2010
2037
  {
2011
2038
  "id": "auto-execute-messaging",
2012
- "label": "Step 15: Complete messages for 10-lead test batch",
2039
+ "label": "Step 15: Complete messages for 15-lead test batch",
2013
2040
  "currentStepValue": "auto-execute-messaging",
2014
2041
  "references": [
2015
2042
  "references/parallel-critique-protocol.md",
@@ -15,7 +15,7 @@ packet.
15
15
 
16
16
  The approval gate used to be the place where the user authorized
17
17
  spend/send-adjacent mutation. It is now compatibility-only. New runs import the
18
- bounded 10-row review batch after source approval, save rubrics and the approved
18
+ bounded 15-row review batch after source approval, save rubrics and the approved
19
19
  message template after post-import review, and only then queue the cascade.
20
20
 
21
21
  If `campaign-shell.json` exists, a draft `CampaignOffer` row already exists but
@@ -47,7 +47,7 @@ Supplied-source preview:
47
47
  - `normal-discovery` is the default when the user does not already know the
48
48
  people/accounts.
49
49
  - `supplied-linkedin-profiles` uses `load_csv_linkedin_leads` before the
50
- 10-lead import batch only as preview/source attachment. Pre-import calls
50
+ 15-lead import batch only as preview/source attachment. Pre-import calls
51
51
  must omit provider-import parameters. Use `campaignOfferId` only to attach the
52
52
  preview/list choice to the campaign UI.
53
53
  - `supplied-domains` uses `load_csv_domains` to create or reuse a
@@ -6,7 +6,7 @@ on every revision round.
6
6
 
7
7
  ## Principle
8
8
 
9
- We spend a bounded review batch (default 25 rows) to prove fit before the
9
+ We spend a bounded review batch (default 15 rows) to prove fit before the
10
10
  user spends credits on hundreds more leads. The sample loop has one job:
11
11
  answer the question "do we have enough real passing examples for the user to
12
12
  judge this campaign?"
@@ -19,7 +19,7 @@ auto-revise leads.
19
19
  ## Inputs
20
20
 
21
21
  - `CampaignOffer.currentStep === "validate-sample"` (set at end of Step 13)
22
- - Imported review batch from Step 13 (size: `importLimit`, default 25)
22
+ - Imported review batch from Step 13 (size: `importLimit`, default 15)
23
23
  - Config from `auto-execute.yaml`: `sample.sampleSize`,
24
24
  `sample.minProjectedPass`, `sample.maxRevisionRounds`
25
25
  - Persisted counter `revisionRound` (starts at 0 on first entry; persists
@@ -51,7 +51,7 @@ auto-revise leads.
51
51
  6. wait_for_rubric_results(sample, targetCount = <cohortSize>)
52
52
  - cohortSize = stats.totalRows of the enrichment batch, or the
53
53
  imported batch count
54
- - default targetCount=25 matches the default review batch, but pass the
54
+ - default targetCount=15 matches the default review batch, but pass the
55
55
  explicit batch count anyway so future larger expansion batches do not
56
56
  accidentally stop early
57
57
  (see §Known Tool Behaviors #3)
@@ -161,8 +161,8 @@ company, enrichCellId, enrichStatus) over the default shape.
161
161
 
162
162
  ### 5. `wait_for_rubric_results` can timeout with enough signal to decide
163
163
 
164
- Observed: a 10-row review batch may return `ready=false`, `reason="timeout"`,
165
- and partial stats such as 9/10 scored, 2 passing, 2 messages generated. That is
164
+ Observed: a 15-row review batch may return `ready=false`, `reason="timeout"`,
165
+ and partial stats such as 13/15 scored, 2 passing, 2 messages generated. That is
166
166
  enough to diagnose an underperforming sample. Waiting again without active
167
167
  processing makes the experience feel frozen.
168
168
 
@@ -178,16 +178,16 @@ or wait once only if active processing is still visible.
178
178
  projectedPass = round(passInSample / sampleSize * importLimit)
179
179
  ```
180
180
 
181
- Worked examples with defaults (sampleSize=25, importLimit=25):
181
+ Worked examples with defaults (sampleSize=15, importLimit=15):
182
182
 
183
- | passInSample | projectedPass | Handoff? (minProjectedPass=5) |
183
+ | passInSample | projectedPass | Handoff? (minProjectedPass=3) |
184
184
  | ------------ | ------------- | ----------------------------- |
185
185
  | 0 | 0 | No — escalate or revise |
186
- | 4 | 4 | No — escalate or revise |
187
- | 5 | 5 | Yes — exactly at floor |
186
+ | 2 | 2 | No — escalate or revise |
187
+ | 3 | 3 | Yes — exactly at floor |
188
+ | 4 | 4 | Yes |
188
189
  | 10 | 10 | Yes |
189
190
  | 15 | 15 | Yes |
190
- | 25 | 25 | Yes |
191
191
 
192
192
  When non-default importLimit/sampleSize are configured, the math scales
193
193
  the same way. In the default review-batch mode, the sample size equals the
@@ -251,8 +251,8 @@ rate is zero with no pattern that brief editing could fix.
251
251
 
252
252
  Signal examples:
253
253
 
254
- - 10/10 rows are wrong function / wrong seniority / wrong geo.
255
- - 8/10 rows enrich to empty strings for the tokens the brief needs.
254
+ - 15/15 rows are wrong function / wrong seniority / wrong geo.
255
+ - 12/15 rows enrich to empty strings for the tokens the brief needs.
256
256
  - Rubric passes 0 rows and the failure reasons are all "not ICP."
257
257
  - **Marketplace supply-side contamination:** >20% of sample rows match
258
258
  the brief §14 forbidden side (e.g. Skillsync sample contains
@@ -95,7 +95,7 @@ Default case — no existing lead list bound to the campaign:
95
95
  ```text
96
96
  import_leads({
97
97
  campaignOfferId,
98
- targetLeadCount: <importLimit from auto-execute.yaml; default 10>
98
+ targetLeadCount: <importLimit from auto-execute.yaml; default 15>
99
99
  })
100
100
  ```
101
101
 
@@ -69,7 +69,7 @@ orient the user after a meaningful step change:
69
69
  - source selected: the campaign should point at the primary provider step
70
70
  - rubrics saved: the campaign should show filter/rubric state
71
71
  - message set approved: the campaign should show message state
72
- - 10-lead test batch imported/generated: the campaign should show the test rows
72
+ - 15-lead test batch imported/generated: the campaign should show the test rows
73
73
  - settings handoff: the campaign should open to Settings for sender attachment
74
74
  - running: the campaign is live
75
75