@sellable/install 0.1.89 → 0.1.91

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.
@@ -17,14 +17,22 @@ Use the inherited Sellable MCP tools when available:
17
17
  - `search_signals` to find recent post lanes. Include `campaignOfferId` whenever
18
18
  the parent provides one so selected searches/lists stay attached to the
19
19
  campaign.
20
- - `fetch_post_engagers` to sample engagers from selected posts.
20
+ - `select_promising_posts` to promote the exact posts you will sample into the
21
+ campaign UI before fetching engagers. In campaign-attached runs, do this
22
+ before the first `fetch_post_engagers` call so the user can see which posts
23
+ are being sampled.
24
+ - `fetch_post_engagers` to sample engagers from promoted/selected posts.
21
25
 
22
26
  Process:
23
27
 
24
28
  1. Read the campaign brief, kickoff doc, or lane prompt supplied by the parent.
25
29
  2. Search 3-5 keyword/topic lanes, favoring fresh posts from the last 7-14 days.
26
- 3. Select 3-5 promising posts when available.
27
- 4. Fetch or sample engagers for selected posts and score rough ICP fit from visible headline/display-name cues only. Do not enrich people during viability estimation.
30
+ 3. Select 3-5 promising posts when available. If a `campaignOfferId` was
31
+ supplied, call `select_promising_posts({ campaignOfferId, selectionMode:
32
+ "replace", selections, headlineICPCriteria, currentStep:
33
+ "signal-discovery" })` before sampling so the watched Signal Discovery table
34
+ shows the promoted posts.
35
+ 4. Fetch or sample engagers for promoted posts and score rough ICP fit from visible headline/display-name cues only. Do not enrich people during viability estimation.
28
36
  5. Estimate usable prospects per selected post from sampled pass rate. If the sample is good but volume is low, say how many more similar posts should be added or scraped.
29
37
  6. Return false positives and dead ends explicitly.
30
38
 
@@ -444,6 +444,9 @@ function codexPluginMcp(opts) {
444
444
  type: "stdio",
445
445
  command,
446
446
  args,
447
+ env: {
448
+ SELLABLE_WATCH_MODE_DRIVER: "codex",
449
+ },
447
450
  },
448
451
  },
449
452
  };
@@ -455,6 +458,9 @@ function codexPluginMcp(opts) {
455
458
  type: "stdio",
456
459
  command: "npx",
457
460
  args: ["-y", opts.mcpPackage],
461
+ env: {
462
+ SELLABLE_WATCH_MODE_DRIVER: "codex",
463
+ },
458
464
  },
459
465
  },
460
466
  };
@@ -601,6 +607,12 @@ data, compare sources by source volume, sampled ICP fit, activity/warmth
601
607
  signals, cleanup risk, and confidence basis. If a user asks for a forecast,
602
608
  label it explicitly as not estimated from this run.
603
609
 
610
+ For campaign-attached Signal Discovery sampling, promote/select the exact posts
611
+ with \`select_promising_posts\` before \`fetch_post_engagers\` so the user can see
612
+ which posts are being sampled in the watched app. The watch guide should say
613
+ that we are pulling sample engagers from these posts to confirm the ICP is
614
+ actually engaging and the source is viable.
615
+
604
616
  Every approval gate must include live campaign access after the readable inline
605
617
  content. Show a \`Watch link:\` line once the campaign shell exists. In normal
606
618
  customer runs, do not show local draft filenames or filesystem paths unless the
@@ -611,46 +623,42 @@ Never mention MCP namespaces, prompt chunking, plugin cache paths, missing
611
623
  linked skill versions, runbooks, or local skill files in normal customer-facing
612
624
  copy.
613
625
 
614
- ## Codex Watch Browser Handoff
626
+ ## Codex Watch Link Handoff
615
627
 
616
- When a campaign tool returns \`watchUrl\`, treat it as an active browser handoff,
617
- not only a URL to print. A valid handoff link must be a safe direct
618
- \`/campaign-builder/{campaignId}?mode=claude\`
619
- URL. \`create_campaign.watchUrl\`, \`create_campaign({ campaignId }).watchUrl\`,
620
- and \`get_campaign.watchUrl\` are all acceptable only when they return that direct
621
- campaign-builder shape, with \`workspaceId\` used only as a safe routing hint when
622
- needed.
628
+ When a campaign tool returns \`watchUrl\`, treat it as a user-opened app link, not
629
+ as permission to drive the browser. A valid handoff link must be a direct
630
+ \`/campaign-builder/{campaignId}?mode=claude|codex\` URL with the auth token and
631
+ workspace routing needed for auto-login. \`create_campaign.watchUrl\`,
632
+ \`create_campaign({ campaignId }).watchUrl\`, and \`get_campaign.watchUrl\` are all
633
+ acceptable only when they return that direct campaign-builder shape.
623
634
 
624
- In Codex Desktop, when in-app browser control is available, open the returned watch link on the user's behalf. After opening it, inspect the browser-visible campaign state, then explain what the user is seeing before continuing with more campaign tools. Use customer language such as:
625
-
626
- \`\`\`text
627
- I’ll open the campaign view and keep it in sync as I build.
628
- \`\`\`
629
-
630
- If browser control is unavailable, provide the watch link without discussing the
631
- runtime limitation. In off-desktop Codex runs, make the direct watch link easy to
632
- copy/open, then continue with explicit customer-facing campaign progress and
633
- \`get_campaign_navigation_state\` orientation checks.
634
- Use this fallback shape:
635
+ Never call browser-opening tools, shell \`open\`, Computer Use, or in-app browser
636
+ automation just because a watch link exists. Print the link and tell the user to
637
+ Command-Enter/click it when they want to watch in the app. Use this shape:
635
638
 
636
639
  \`\`\`text
637
640
  Watch link: {watchUrl}
638
641
 
639
- I’ll keep the campaign brief, lead source, and message-review steps explicit
640
- here as I build.
642
+ Command-Enter or click that link to watch the campaign in Sellable. I’ll keep
643
+ the brief, lead source, and message-review steps explicit here as I build.
641
644
  \`\`\`
642
645
 
643
- If opening the watch link lands on an auth, 404, permission, blank, or visible
644
- error state, report only what is visible, recover a fresh watch link once
645
- with \`create_campaign({ campaignId })\` or \`get_campaign\`, and try that link.
646
- Do not claim the browser was opened, inspected, or synchronized unless the
647
- visible browser state was actually observed. Do not claim the browser was opened
648
- unless it was opened and observed.
646
+ The watch link should auto-login through the token in the URL. If the user says
647
+ the link lands on auth, 404, permission, blank, or a visible error state, recover
648
+ a fresh watch link once with \`create_campaign({ campaignId })\` or \`get_campaign\`
649
+ and print that link. Do not claim the browser was opened, inspected, or
650
+ synchronized.
649
651
 
650
652
  After every \`update_campaign({ campaignId, currentStep })\`, use
651
653
  \`get_campaign_navigation_state\` when available as a compact orientation check:
652
- match the browser-visible step to the saved campaign state, explain the current
653
- state in one sentence, and only then continue. Sender selection belongs at Settings after message approval and 10-row validation. After message validation, use Settings to help the user connect or select a LinkedIn sender. Explain Slack reply review before launch. After sender selection, attach the recommended sequence and move the watched UI to Send. Do not start the campaign or trigger a live send unless the user explicitly confirms that launch action outside UAT.
654
+ match the saved campaign state to the expected watch-link step, explain the
655
+ current state in one sentence, and only then continue. Sender selection belongs
656
+ at Settings after message approval and 10-row validation. After message
657
+ validation, use Settings to help the user connect or select a LinkedIn sender.
658
+ Explain Slack reply review before launch. After sender selection, attach the
659
+ recommended sequence and move the watched UI to Send. Do not start the campaign
660
+ or trigger a live send unless the user explicitly confirms that launch action
661
+ outside UAT.
654
662
 
655
663
  ## Names To Use
656
664
 
@@ -1516,6 +1524,10 @@ exec npx -y ${INSTALL_PACKAGE_SPEC} "$@"
1516
1524
  writeFile(binPath, shim, opts, 0o755);
1517
1525
  }
1518
1526
 
1527
+ function withWatchModeDriver(command, args, driver) {
1528
+ return ["env", [`SELLABLE_WATCH_MODE_DRIVER=${driver}`, command, ...args]];
1529
+ }
1530
+
1519
1531
  function mcpCommand(opts) {
1520
1532
  if (opts.server === "package") {
1521
1533
  return ["npx", ["-y", opts.mcpPackage]];
@@ -1534,6 +1546,12 @@ function mcpCommand(opts) {
1534
1546
  return ["hosted", [opts.hostedUrl]];
1535
1547
  }
1536
1548
 
1549
+ function mcpCommandForHost(opts, driver) {
1550
+ const [command, args] = mcpCommand(opts);
1551
+ if (command === "hosted") return [command, args];
1552
+ return withWatchModeDriver(command, args, driver);
1553
+ }
1554
+
1537
1555
  function installClaude(opts) {
1538
1556
  if (!commandExists("claude")) {
1539
1557
  const message =
@@ -1554,7 +1572,7 @@ function installClaude(opts) {
1554
1572
  patchClaudeAlwaysLoad(opts);
1555
1573
  return true;
1556
1574
  }
1557
- const [command, args] = mcpCommand(opts);
1575
+ const [command, args] = mcpCommandForHost(opts, "claude");
1558
1576
  run("claude", ["mcp", "remove", "sellable"], {
1559
1577
  ...opts,
1560
1578
  dryRun: opts.dryRun,
@@ -1636,7 +1654,7 @@ function installCodex(opts) {
1636
1654
  const info = installCodexDesktopPlugin(opts);
1637
1655
  return { installed: true, ...info };
1638
1656
  }
1639
- const [command, args] = mcpCommand(opts);
1657
+ const [command, args] = mcpCommandForHost(opts, "codex");
1640
1658
  run("codex", ["mcp", "remove", "sellable"], {
1641
1659
  ...opts,
1642
1660
  dryRun: opts.dryRun,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/install",
3
- "version": "0.1.89",
3
+ "version": "0.1.91",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code and Codex",
6
6
  "bin": {
@@ -134,6 +134,12 @@ claim they ran in parallel and do not surface install status to the customer. In
134
134
  chat, call the downstream copy stage `message generation`;
135
135
  `message-validation.md` is only an internal proof artifact.
136
136
 
137
+ For campaign-attached Signal Discovery sampling, promote/select the exact posts
138
+ with `select_promising_posts` before `fetch_post_engagers` so the user can see
139
+ which posts are being sampled in the watched app. The watch guide should say
140
+ that we are pulling sample engagers from these posts to confirm the ICP is
141
+ actually engaging and the source is viable.
142
+
137
143
  After find-leads returns a lead source and the user approves it, use the same
138
144
  registry pattern for the two post-lead branches. The create-campaign-v2 subskill
139
145
  calls `get_post_find_leads_scout_registry`, then launches the returned
@@ -159,45 +165,42 @@ linked skill versions, runbooks, npm/package details, repo-local files, VPS or
159
165
  browser automation limitations, or local skill files in normal customer-facing
160
166
  copy.
161
167
 
162
- ## Codex Watch Browser Handoff
168
+ ## Codex Watch Link Handoff
163
169
 
164
- When a campaign tool returns `watchUrl`, treat it as an active browser handoff,
165
- not only a URL to print. A valid handoff link must be a safe direct
166
- `/campaign-builder/{campaignId}?mode=claude` URL. `create_campaign.watchUrl`,
170
+ When a campaign tool returns `watchUrl`, treat it as a user-opened app link, not
171
+ as permission to drive the browser. A valid handoff link must be a direct
172
+ `/campaign-builder/{campaignId}?mode=claude|codex` URL with the auth token and
173
+ workspace routing needed for auto-login. `create_campaign.watchUrl`,
167
174
  `create_campaign({ campaignId }).watchUrl`, and `get_campaign.watchUrl` are all
168
- acceptable only when they return that direct campaign-builder shape, with
169
- `workspaceId` used only as a safe routing hint when needed.
170
-
171
- In Codex Desktop, when in-app browser control is available, open the returned watch link on the user's behalf. After opening it, inspect the browser-visible campaign state, then explain what the user is seeing before continuing with more campaign tools. Use customer language such as:
172
-
173
- ```text
174
- I’ll open the campaign view and keep it in sync as I build.
175
- ```
175
+ acceptable only when they return that direct campaign-builder shape.
176
176
 
177
- If browser control is unavailable, provide the watch link without discussing the
178
- runtime limitation. In off-desktop Codex runs, make the direct watch link easy
179
- to copy/open, then continue with explicit customer-facing campaign progress and
180
- `get_campaign_navigation_state` orientation checks.
181
- Use this fallback shape:
177
+ Never call browser-opening tools, shell `open`, Computer Use, or in-app browser
178
+ automation just because a watch link exists. Print the link and tell the user to
179
+ Command-Enter/click it when they want to watch in the app. Use this shape:
182
180
 
183
181
  ```text
184
182
  Watch link: {watchUrl}
185
183
 
186
- I’ll keep the campaign brief, lead source, and message-review steps explicit
187
- here as I build.
184
+ Command-Enter or click that link to watch the campaign in Sellable. I’ll keep
185
+ the brief, lead source, and message-review steps explicit here as I build.
188
186
  ```
189
187
 
190
- If opening the watch link lands on an auth, 404, permission, blank, or visible
191
- error state, report only what is visible, recover a fresh watch link once with
192
- `create_campaign({ campaignId })` or `get_campaign`, and try that link. Do not
193
- claim the browser was opened, inspected, or synchronized unless the visible
194
- browser state was actually observed. Do not claim the browser was opened unless
195
- it was opened and observed.
188
+ The watch link should auto-login through the token in the URL. If the user says
189
+ the link lands on auth, 404, permission, blank, or a visible error state, recover
190
+ a fresh watch link once with `create_campaign({ campaignId })` or `get_campaign`
191
+ and print that link. Do not claim the browser was opened, inspected, or
192
+ synchronized.
196
193
 
197
194
  After every `update_campaign({ campaignId, currentStep })`, use
198
195
  `get_campaign_navigation_state` when available as a compact orientation check:
199
- match the browser-visible step to the saved campaign state, explain the current
200
- state in one sentence, and only then continue. Sender selection belongs at Settings after message approval and 10-row validation. After message validation, use Settings to help the user connect or select a LinkedIn sender. Explain Slack reply review before launch. After sender selection, attach the recommended sequence and move the watched UI to Send. Do not start the campaign or trigger a live send unless the user explicitly confirms that launch action outside UAT.
196
+ match the saved campaign state to the expected watch-link step, explain the
197
+ current state in one sentence, and only then continue. Sender selection belongs
198
+ at Settings after message approval and 10-row validation. After message
199
+ validation, use Settings to help the user connect or select a LinkedIn sender.
200
+ Explain Slack reply review before launch. After sender selection, attach the
201
+ recommended sequence and move the watched UI to Send. Do not start the campaign
202
+ or trigger a live send unless the user explicitly confirms that launch action
203
+ outside UAT.
201
204
 
202
205
  ## Names To Use
203
206