@sellable/mcp 0.1.186 → 0.1.188

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.
@@ -306,14 +306,18 @@ copy.
306
306
  ## Codex Watch Link Handoff
307
307
 
308
308
  When a campaign tool returns `watchUrl`, treat it as a user-opened app link, not
309
- as permission to drive the browser. A valid handoff link must be a direct
310
- `/campaign-builder/{campaignId}?mode=claude|codex` URL with the auth token and
311
- workspace routing needed for auto-login. `create_campaign.watchUrl`,
309
+ as permission to drive the browser. A valid first handoff link must be the exact
310
+ `create_campaign.watchUrl` value: a direct
311
+ `/campaign-builder/{campaignId}?mode=claude|codex` URL with `workspaceId` and
312
+ `token` query parameters for auto-login. `create_campaign.watchUrl`,
312
313
  `create_campaign({ campaignId }).watchUrl`, and `get_campaign.watchUrl` are all
313
- acceptable only when they return that direct campaign-builder shape.
314
+ acceptable only when they return that direct campaign-builder shape. Never
315
+ derive, shorten, reconstruct, or print a bare `/campaign-builder/{campaignId}`
316
+ URL.
314
317
 
315
318
  Never call browser-opening tools, shell `open`, Computer Use, or in-app browser
316
- automation just because a watch link exists. Print the link in this shape:
319
+ automation just because a watch link exists. Print the first watch link exactly
320
+ once, directly before the brief approval question, in this shape:
317
321
 
318
322
  ```text
319
323
  Campaign shell is ready. We'll keep building the campaign in this chat.
@@ -335,6 +339,9 @@ Never print a placeholder watch link such as "Open campaign" or "link will
335
339
  update once the shell is created." If the shell is not created yet, call
336
340
  `create_campaign` first. If `create_campaign` does not return `watchUrl`, stop
337
341
  and surface the missing watch-link error before lead sourcing.
342
+ Do not print another `Watch link:` line during source/provider selection or
343
+ normal approval turns unless the user explicitly asks for the link or you are
344
+ recovering a missing/broken URL.
338
345
 
339
346
  After every `update_campaign({ campaignId, currentStep })`, use
340
347
  `get_campaign_navigation_state` when available as a compact orientation check:
@@ -556,14 +563,15 @@ the run. Treat YOLO as `interactionMode: "autonomous"` plus an intake policy:
556
563
  Before the identity gate, use this customer-facing shape:
557
564
 
558
565
  ```text
559
- I’m ready to build the campaign in {workspace}.
566
+ You're in {workspace}.
560
567
 
561
- First I’ll research the person/company this campaign is for. I’ll use that
562
- context to recommend a target, offer, proof, and lead source, then you can
563
- correct anything stale before I build from it.
568
+ Excited to help you launch your LinkedIn outbound campaign.
564
569
 
565
- Then I’ll turn that into a campaign brief for you to approve before any leads
566
- are sourced.
570
+ We're at setup: first I'll use your LinkedIn profile to understand the company,
571
+ then I'll draft the campaign brief, help choose where to find buyers, review
572
+ messages, and wait for final launch approval.
573
+
574
+ What's your LinkedIn profile URL or handle?
567
575
  ```
568
576
 
569
577
  Do not silently ask Codex intake or approval questions as plain chat when
@@ -688,26 +696,27 @@ updates.
688
696
  been written. Your IMMEDIATE next visible message branches on
689
697
  `isReturningUser` from the tool result:
690
698
 
691
- - If `isReturningUser === true`, prepend ONE line acknowledging the
692
- reused workspace, then the locked Step 3 narration verbatim
693
- (substituting `activeWorkspaceName` exactly):
699
+ - If `isReturningUser === true`, use `activeWorkspaceName` when present,
700
+ otherwise `activeWorkspaceId`, as `{workspaceLabel}`:
694
701
 
695
702
  ```text
696
- You're in {activeWorkspaceName} workspace, ready to roll.
697
- ```
703
+ You're in {workspaceLabel}.
698
704
 
699
- What is your LinkedIn profile URL or handle?
705
+ Excited to help you launch your LinkedIn outbound campaign. We're at setup: first I'll use your LinkedIn profile to understand the company, then I'll draft the campaign brief, help choose where to find buyers, review messages, and wait for final launch approval.
700
706
 
701
- ````
707
+ What's your LinkedIn profile URL or handle?
708
+ ```
702
709
 
703
- - If `isReturningUser === false`, prepend ONE line confirming the new
704
- workspace, then the locked Step 3 narration verbatim:
710
+ - If `isReturningUser === false`, use `activeWorkspaceName` when present,
711
+ otherwise `activeWorkspaceId`, as `{workspaceLabel}`:
705
712
 
706
- ```text
707
- You're set up your {activeWorkspaceName} workspace is ready.
713
+ ```text
714
+ You're set up in {workspaceLabel}.
715
+
716
+ Excited to help you launch your LinkedIn outbound campaign. We're at setup: first I'll use your LinkedIn profile to understand the company, then I'll draft the campaign brief, help choose where to find buyers, review messages, and wait for final launch approval.
708
717
 
709
- What is your LinkedIn profile URL or handle?
710
- ````
718
+ What's your LinkedIn profile URL or handle?
719
+ ```
711
720
 
712
721
  No other lines. No "all set", no "signed in", no other acknowledgement.
713
722
 
@@ -6,11 +6,9 @@ visibility: internal
6
6
 
7
7
  # Create Campaign v2
8
8
 
9
- You are the create-campaign-v2 orchestrator. Run the active state machine in
10
- `core/flow.v2.json`; load deeper references only at the stage that needs them.
11
- This is the fast entry point.
12
-
13
- Load the compact flow when you need exact gates:
9
+ fast entry point. Run the active state machine in `core/flow.v2.json`;
10
+ load deeper references only at the stage that needs them.
11
+ Load the compact flow for exact gates:
14
12
 
15
13
  ```text
16
14
  get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "core/flow.v2.json" })
@@ -23,14 +21,12 @@ validate-sample tool:
23
21
  get_subskill_prompt({ subskillName: "create-campaign-v2-tail" })
24
22
  ```
25
23
 
26
- CampaignOffer state is canonical. CampaignOffer state and the watch link are
27
- canonical. Resume, gating, and handoff read campaign state first: `campaignId`,
28
- `watchUrl`, `campaignBrief`, `currentStep`, source/search
29
- association, `selectedLeadListId`, `workflowTableId`, `leadScoringRubrics`,
30
- `approvedMessageTemplate`, `senderIds`, `sequenceTemplate`, and running state.
31
- Local draft files are debug outputs; do not create, link, or surface them in
32
- normal runs; these files are debug outputs; resume and gating read campaign
33
- state first.
24
+ CampaignOffer state and watch link are canonical. Resume, gates, and handoffs
25
+ read campaign state first: `campaignId`, `watchUrl`, `campaignBrief`,
26
+ `currentStep`, source/search association, `selectedLeadListId`,
27
+ `workflowTableId`, `leadScoringRubrics`, `approvedMessageTemplate`,
28
+ `senderIds`, `sequenceTemplate`, and running state. Local draft files are
29
+ debug-only; do not create, link, or surface them in normal runs.
34
30
 
35
31
  ## Normal Flow
36
32
 
@@ -57,13 +53,19 @@ Legacy commit-gate/atomic-mint is only in create-campaign-v2-validation.
57
53
  ## Identity-First Campaign Setup
58
54
 
59
55
  Do not treat the active workspace as the campaign subject. Resolve the
60
- client/company, then confirm target, offer, trust proof, and prospect source
61
- before drafting the brief.
56
+ client/company, then confirm target, offer, proof, and source before the brief.
62
57
 
63
- First visible request when no identity is known:
58
+ First visible request when no identity is known, after showing the active
59
+ workspace from auth/bootstrap:
64
60
 
65
61
  ```text
66
- What is your LinkedIn profile URL or handle?
62
+ Excited to help you launch your LinkedIn outbound campaign.
63
+
64
+ We're at setup: first I'll use your LinkedIn profile to understand the company,
65
+ then I'll draft the campaign brief, help choose where to find buyers, review
66
+ messages, and wait for final launch approval.
67
+
68
+ What's your LinkedIn profile URL or handle?
67
69
  ```
68
70
 
69
71
  Require a LinkedIn profile URL or handle before setup continues. Normalize
@@ -92,7 +94,7 @@ a sender picker during setup. Sender availability belongs only
92
94
  to Settings after message approval and campaign setup validation.
93
95
 
94
96
  Use `research-sender`, call `complete_sender_research` before shell creation,
95
- and carry proof gaps into the brief when web tools are unavailable.
97
+ and carry proof gaps into the brief.
96
98
 
97
99
  ## Brief Provenance
98
100
 
@@ -117,8 +119,10 @@ must not include quoted first-message copy. If a message-shape hint is useful,
117
119
  keep it as non-final bullets and say: "This is not the message yet; I will write
118
120
  real examples after we find and filter leads."
119
121
 
120
- Keep brief approval positive: no "does not approve..." list. Ask
121
- approve/revise, then choose where to find buyers.
122
+ Keep brief approval positive: no "does not approve..." list. The first brief
123
+ must be visible exactly once before the approval question. If it was rendered
124
+ immediately before `create_campaign`, do not render it again after the shell is
125
+ created; append the one watch-link handoff, then ask approve/revise.
122
126
 
123
127
  ## YOLO Mode
124
128
 
@@ -150,12 +154,18 @@ when a bounded choice needs an escape hatch.
150
154
 
151
155
  ## Watch Link And Narration
152
156
 
153
- The first shell is created before lead import so the user can watch the work.
154
- Print the returned `watchUrl` once, before brief approval. Later normal updates
155
- and approval turns must not print `Watch link:`; update `currentStep` and
156
- `watchNarration` so the already-open app changes live. Reprint only on user
157
- request or missing/broken URL recovery. Never call browser-opening tools,
158
- Computer Use, shell `open`, or in-app browser automation just because a watch
157
+ The first campaign shell is created before lead import so the user can watch
158
+ the work. When `create_campaign` returns `watchUrl`, print that exact value
159
+ once, directly before the brief approval question. The first watch link must be
160
+ a direct `/campaign-builder/{campaignId}?mode={claude|codex}` URL containing
161
+ `workspaceId` and `token`. Never derive, shorten, reconstruct, or print a bare
162
+ `/campaign-builder/{campaignId}` URL. If the returned `watchUrl` is missing or
163
+ does not include `mode`, `workspaceId`, and `token`, recover a fresh link with
164
+ `create_campaign({ campaignId })` or `get_campaign` before asking for approval.
165
+ Later normal updates and approval turns must not print `Watch link:`; update
166
+ `currentStep` and `watchNarration` so the already-open app changes live. Reprint
167
+ only if asked or for missing/broken URL recovery. Never call browser-opening
168
+ tools, Computer Use, shell `open`, or browser automation just because a watch
159
169
  link exists.
160
170
 
161
171
  Every watched step switch must call:
@@ -171,18 +181,17 @@ copy.
171
181
 
172
182
  ## Lead Source
173
183
 
174
- Default source order when source is unspecified: LinkedIn post engagement,
175
- Sales Nav recent activity, broader Sales Nav title search, then Prospeo. Use that order only
176
- when the campaign is not hiring-led and does not need hiring-by-role signals.
177
- If the campaign is hiring-led or needs hiring-by-role signals, start with
178
- Prospeo because `search_prospeo` supports
179
- `company_job_posting_hiring_for` and `company_job_posting_quantity`; Sales Nav
180
- is only an activity/referral fallback because it does not provide hiring-by-role filters.
184
+ Default source order when unspecified: LinkedIn post engagement, Sales Nav
185
+ recent activity, broader Sales Nav title search, then Prospeo, unless the
186
+ campaign is hiring-led. For hiring-by-role signals, start with Prospeo because
187
+ `search_prospeo` supports `company_job_posting_hiring_for` and
188
+ `company_job_posting_quantity`; Sales Nav is only an activity/referral fallback.
181
189
 
182
190
  Before any provider prompt/search/scout call, move the watched campaign to
183
191
  provider/source selection, then show one `## Find Buyers Plan` gate before
184
- `request_user_input`, without repeating the watch URL. This approval only
185
- authorizes finding where to look. It does not add anyone yet. Write:
192
+ `request_user_input`, without repeating the watch URL. The plan must appear in
193
+ chat before the question. This approval only authorizes finding where to look.
194
+ It does not add anyone yet. Write:
186
195
 
187
196
  - the buyer groups or places we could check
188
197
  - the best place to start
@@ -252,41 +261,13 @@ export count, not the campaign execution-slice size. For Signal Discovery, pass
252
261
  `provider: "signal-discovery"`, `targetEngagerCount`, `maxPostsToScrape`, and
253
262
  `confirmed: true`; the tool owns moving the watch UI to source-list progress
254
263
  after a lead-list/job id exists.
264
+ After `import_leads`, poll `wait_for_lead_list_ready` until ready, failed, or
265
+ cancelled. Rows appearing is not enough for `confirm_lead_list`; use
266
+ `allowPartialSourceList: true` only when the user explicitly asks to continue early.
255
267
 
256
- For LinkedIn engagement, use this compact source-action approval shape after
257
- selected posts exist:
258
-
259
- ```markdown
260
- ## Source Recommendation
261
-
262
- Start with LinkedIn posts.
263
-
264
- I found 3 posts worth checking first.
265
-
266
- **Goal:** find about 300 likely prospects<br>
267
- **People to check:** about 1,500 people who reacted or commented<br>
268
- **Good sign:** at least 10% of the first sample looks like real prospects; below
269
- that, switch to active LinkedIn profiles with the right titles<br>
270
- **First review:** after the list is built, review the first 15 leads before we
271
- scale<br>
272
-
273
- ### Recommended posts
274
-
275
- Show author/topic, why it fits, public activity, and people we can check.
276
-
277
- **Public activity in the selected posts:** ~2,800 reactions/comments<br>
278
- **Likely prospects:** ~560 before cleanup
279
-
280
- ### Recommendation
281
-
282
- Approve scraping these 3 posts.
283
-
284
- After approval, I'll build the source list, add it to the campaign, and
285
- review the first 15 leads before we scale.
286
-
287
- **Fallback:** if the first sample is too noisy or has too few prospects,
288
- switch to active LinkedIn profiles with the right titles.
289
- ```
268
+ For LinkedIn engagement, the source-action approval uses `## Source
269
+ Recommendation`, plain language, selected posts, people to check, likely
270
+ prospects, cleanup risk, fallback, and the first 15-lead review.
290
271
 
291
272
  A source recommendation must show concrete evidence: source path, filters or
292
273
  recipe, raw volume, sample size, sampled fits as n/N plus percentage/range,
@@ -243,12 +243,13 @@ call, move the watched campaign to the provider/source page, then give the user
243
243
  a compact source plan in grade-5 language: "here are the places we could look, I
244
244
  recommend starting here, here is why, and here is where I'll look next if this
245
245
  is too thin." The order matters: show the plan in normal chat first, then open
246
- the approval question. Ask them to approve that plan or choose
247
- a different source. Use plain customer language for the boundary: "This only
248
- approves me to look for the best places to find buyers. I won't add anyone
249
- yet." After brief approval, say "Brief approved. Next, we'll choose where to
250
- find buyers. I won't add anyone yet." Do not say "lead-source scouting",
251
- "source scouting", or "not importing leads" in the customer-facing transition.
246
+ the approval question. Do not reprint the watch link during source/provider
247
+ selection. Ask them to approve that plan or choose a different source. Use plain
248
+ customer language for the boundary: "This only approves me to look for the best
249
+ places to find buyers. I won't add anyone yet." After brief approval, say
250
+ "Brief approved. Next, we'll choose where to find buyers. I won't add anyone
251
+ yet." Do not say "lead-source scouting", "source scouting", or "not importing
252
+ leads" in the customer-facing transition.
252
253
  Customer-facing source-plan copy must avoid "lane", "provider",
253
254
  "lead-source scouting", "source scouting", "precision/scale tradeoff", "evidence quality",
254
255
  "pilot volume", "workflow pain", and "ICP". Use "buyers" for the target market,
@@ -339,6 +340,11 @@ Send changes here. I'll ask for your approval whenever I need your expertise or
339
340
  taste before moving forward.
340
341
  ```
341
342
 
343
+ Print that watch-link handoff only once before the brief approval question, and
344
+ only with the exact tokenized `create_campaign.watchUrl`. If the brief was
345
+ already shown immediately before shell creation, do not show the brief again;
346
+ append the handoff and ask the approval question.
347
+
342
348
  In customer-facing copy, do not say "campaign identity" or ask what the user
343
349
  wants to "sell first." Say "sender and company" for the person/company context,
344
350
  and ask what we should "pitch to prospects first" for the offer/CTA choice.