@sellable/install 0.1.195 → 0.1.197

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.
package/README.md CHANGED
@@ -70,15 +70,18 @@ source-scout agents.
70
70
  Use the same public entrypoints in both hosts:
71
71
 
72
72
  - Claude Code: `/sellable:create-campaign`
73
+ - Claude Code: `/sellable:create-ab-test`
73
74
  - Claude Code: `/sellable:foundation`
74
75
  - Claude Code: `/sellable:content`
75
76
  - Claude Code: `/sellable:create-post`
76
77
  - Codex: `$sellable:create-campaign`
78
+ - Codex: `$sellable:create-ab-test`
77
79
  - Codex: `$sellable:foundation`
78
80
  - Codex: `$sellable:content`
79
81
  - Codex: `$sellable:create-post`
80
82
  - Codex Desktop plugin: `sellable@sellable`
81
83
  - Codex visible skill: `Sellable Create Campaign`
84
+ - Codex visible skill: `Sellable Create A/B Test`
82
85
  - Codex visible skill: `Sellable Foundation`
83
86
  - Codex visible skill: `Sellable Content`
84
87
  - Codex visible skill: `Sellable Create Post`
@@ -180,6 +180,7 @@ function printCreateCommandHint() {
180
180
  console.log("");
181
181
  printAgentBox("Using Claude Code?", "claude", [
182
182
  { label: "Campaign", command: "/sellable:create-campaign" },
183
+ { label: "A/B Test", command: "/sellable:create-ab-test" },
183
184
  { label: "Foundation", command: "/sellable:foundation" },
184
185
  { label: "Content", command: "/sellable:content" },
185
186
  { label: "Post", command: "/sellable:create-post" },
@@ -188,6 +189,7 @@ function printCreateCommandHint() {
188
189
  console.log("");
189
190
  printAgentBox("Using Codex?", "codex", [
190
191
  { label: "Campaign", command: "$sellable:create-campaign" },
192
+ { label: "A/B Test", command: "$sellable:create-ab-test" },
191
193
  { label: "Foundation", command: "$sellable:foundation" },
192
194
  { label: "Content", command: "$sellable:content" },
193
195
  { label: "Post", command: "$sellable:create-post" },
@@ -618,6 +620,9 @@ const CREATE_CAMPAIGN_ALLOWED_TOOLS = [
618
620
  "mcp__sellable__select_campaign_cells",
619
621
  "mcp__sellable__queue_campaign_cells",
620
622
  "mcp__sellable__wait_for_campaign_processing",
623
+ "mcp__sellable__start_prepare_campaign_messages",
624
+ "mcp__sellable__get_prepare_campaign_messages_status",
625
+ "mcp__sellable__cancel_prepare_campaign_messages",
621
626
  "mcp__sellable__revise_message_template_and_rerun",
622
627
  "mcp__sellable__update_campaign_brief",
623
628
  "mcp__sellable__update_campaign",
@@ -1196,6 +1201,40 @@ then retry \`get_subskill_prompt\`.
1196
1201
  `;
1197
1202
  }
1198
1203
 
1204
+ function createAbTestSkillMd() {
1205
+ try {
1206
+ const here = dirname(fileURLToPath(import.meta.url));
1207
+ const templatePath = join(
1208
+ here,
1209
+ "..",
1210
+ "skill-templates",
1211
+ "create-ab-test.md"
1212
+ );
1213
+ if (existsSync(templatePath)) {
1214
+ return readFileSync(templatePath, "utf8");
1215
+ }
1216
+ } catch {
1217
+ // fall through to hardcoded fallback below
1218
+ }
1219
+ return `---
1220
+ name: create-ab-test
1221
+ description: Create a Sellable campaign A/B test from a clean source lead list.
1222
+ visibility: public
1223
+ allowed-tools:
1224
+ - mcp__sellable__get_auth_status
1225
+ - mcp__sellable__get_active_workspace
1226
+ - mcp__sellable__get_campaign
1227
+ - mcp__sellable__prepare_campaign_ab_test
1228
+ - mcp__sellable__load_csv_linkedin_leads
1229
+ - mcp__sellable__wait_for_lead_list_ready
1230
+ ---
1231
+
1232
+ # Sellable Create A/B Test
1233
+
1234
+ Use \`prepare_campaign_ab_test\` to create clean A/B split lead lists and review-copy campaigns. Do not call \`export_table_csv\` from generated campaign workflow tables as lead source data, and do not call \`start_campaign\`.
1235
+ `;
1236
+ }
1237
+
1199
1238
  function genericSellableSkillMd({ name, title, description }) {
1200
1239
  return `---
1201
1240
  name: ${name}
@@ -1371,7 +1410,7 @@ then retry \`get_subskill_prompt\`.
1371
1410
  function createPostSkillMd() {
1372
1411
  return `---
1373
1412
  name: create-post
1374
- description: Capture rough LinkedIn post ideas, develop a valuable premise, research current hooks and market beliefs, then save validated drafts in the user's voice.
1413
+ description: Capture rough LinkedIn post ideas, develop a valuable premise, research current hooks and audience tension, then save validated drafts in the user's voice.
1375
1414
  allowed-tools:
1376
1415
  - mcp__sellable__get_auth_status
1377
1416
  - mcp__sellable__get_subskill_prompt
@@ -1382,9 +1421,15 @@ allowed-tools:
1382
1421
  - mcp__sellable__get_post_idea
1383
1422
  - mcp__sellable__list_post_ideas
1384
1423
  - mcp__sellable__save_hook_research
1424
+ - mcp__sellable__calculate_linkedin_hook_preview
1425
+ - mcp__sellable__render_linkedin_post_preview
1385
1426
  - mcp__sellable__save_post_draft
1427
+ - mcp__sellable__update_post_draft
1428
+ - mcp__sellable__list_post_draft_iterations
1386
1429
  - mcp__sellable__get_post_draft
1387
1430
  - mcp__sellable__mark_post_published
1431
+ - mcp__sellable__get_published_post
1432
+ - mcp__sellable__update_published_post_metrics
1388
1433
  - mcp__sellable__list_published_posts
1389
1434
  - mcp__sellable__search_engagement_posts
1390
1435
  - mcp__sellable__fetch_linkedin_posts
@@ -1397,7 +1442,7 @@ allowed-tools:
1397
1442
 
1398
1443
  Use this as the customer-facing entrypoint for the Sellable \`create-post\`
1399
1444
  workflow. It captures raw LinkedIn post ideas, preserves the user's source
1400
- wording, researches currently working hooks, extracts market beliefs, develops
1445
+ wording, researches currently working hooks, extracts audience tension, develops
1401
1446
  a premise with story/tension/reader value, validates proof/voice/AI tells, and
1402
1447
  saves drafts under \`~/.sellable/content/linkedin/**\`.
1403
1448
 
@@ -1633,6 +1678,12 @@ function codexPluginSkills() {
1633
1678
  skillMd: createCampaignSkillMd(),
1634
1679
  soulMd: createCampaignSoulMd(),
1635
1680
  },
1681
+ {
1682
+ dir: "sellable-create-ab-test",
1683
+ displayName: "Sellable Create A/B Test",
1684
+ description: "Create clean A/B campaign review copies",
1685
+ skillMd: createAbTestSkillMd(),
1686
+ },
1636
1687
  {
1637
1688
  dir: "sellable-content",
1638
1689
  displayName: "Sellable Content",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/install",
3
- "version": "0.1.195",
3
+ "version": "0.1.197",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code and Codex",
6
6
  "bin": {
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: create-ab-test
3
+ description: Create a Sellable campaign A/B test from a clean source lead list.
4
+ visibility: public
5
+ allowed-tools:
6
+ - mcp__sellable__get_auth_status
7
+ - mcp__sellable__get_active_workspace
8
+ - mcp__sellable__get_campaign
9
+ - mcp__sellable__get_campaign_context
10
+ - mcp__sellable__get_campaign_navigation_state
11
+ - mcp__sellable__get_campaign_messages_preview
12
+ - mcp__sellable__prepare_campaign_ab_test
13
+ - mcp__sellable__load_csv_linkedin_leads
14
+ - mcp__sellable__wait_for_lead_list_ready
15
+ - mcp__sellable__get_table_rows
16
+ - mcp__sellable__get_rows_minimal
17
+ ---
18
+
19
+ # Sellable Create A/B Test
20
+
21
+ Use this workflow when the user asks to create an A/B campaign test, split a
22
+ campaign into variants, duplicate a campaign for copy testing, or compare two
23
+ campaign-message approaches from the same source list.
24
+
25
+ ## Opening Contract
26
+
27
+ Start by identifying the campaign idea and the one variable being tested. A
28
+ source campaign and clean source lead list are both optional: use an existing
29
+ campaign when the user already has one, use a clean source lead list when leads
30
+ are already available, or use only the idea by writing a campaign name and base
31
+ brief for A. The tool creates A first, duplicates A into B, applies the B delta,
32
+ and stops for review. The goal is two review-copy campaigns, not a launched
33
+ campaign.
34
+
35
+ ## Required Flow
36
+
37
+ 1. Decide the source mode:
38
+ - Existing campaign mode: confirm the source campaign ID or resolve it with
39
+ `get_campaign`.
40
+ - Idea-first mode: write a proper campaign name and base campaign brief from
41
+ the user's idea. If the user also has leads, confirm the clean source
42
+ lead-list ID or use `load_csv_linkedin_leads` first.
43
+ 2. Confirm the A/B variable in plain language. Keep variant B as the explicit
44
+ change and leave variant A as the control unless the user names an A change.
45
+ 3. If a source lead list is supplied, verify it is clean. A clean source list is
46
+ a lead-list or signal-lead-list table, not the generated campaign workflow
47
+ table.
48
+ 4. Call `prepare_campaign_ab_test` with `dryRun: true` first.
49
+ 5. Review split counts, duplicate/skipped counts, campaign names, and variant
50
+ brief deltas with the user.
51
+ 6. Only after review, call `prepare_campaign_ab_test` without `dryRun` using the
52
+ same `idempotencyKey` if one was returned or supplied.
53
+ 7. Return the A and B campaign IDs, split lead-list IDs, counts, and the
54
+ explicit note that both campaigns are `not_started`.
55
+
56
+ ## Tool Inputs
57
+
58
+ Use one of these shapes:
59
+
60
+ - Existing campaign mode: pass `sourceCampaignId`, `variantName`,
61
+ `variantBriefDelta`, and any optional split or A-variant fields.
62
+ - Idea-first mode: omit `sourceCampaignId`, pass `campaignName`,
63
+ `campaignBrief`, `variantName`, and `variantBriefDelta`. If a clean lead list
64
+ is available, also pass `sourceLeadListId`; otherwise leave it out. The tool
65
+ creates the A campaign, then duplicates A to create B and applies the B brief
66
+ delta.
67
+
68
+ ## Anti-Patterns
69
+
70
+ - Do not call `export_table_csv` from an enriched/generated campaign workflow
71
+ table as the lead source for A/B splitting.
72
+ - Do not reimport workflow output columns such as `ICP Score`, `Passes Rubric`,
73
+ `Generate Message`, `Message`, `Approved`, scheduling, status, result, or
74
+ error columns.
75
+ - Do not use broad workflow-table selectors to split decorated campaign rows.
76
+ - Do not call `start_campaign`, approve launch, attach senders for launch, or
77
+ trigger live sends in this workflow.
78
+
79
+ ## Clean Source Fallback
80
+
81
+ If the source campaign has no clean source lead list, or the source list is
82
+ polluted with workflow/output columns, ask for the original CSV or clean source
83
+ list. Use `load_csv_linkedin_leads`; it strips Sellable workflow columns if a
84
+ contaminated CSV is supplied, then creates a clean lead list. If no clean source
85
+ is available, continue in idea-first mode without `sourceLeadListId`.
86
+
87
+ ## Output Contract
88
+
89
+ Report:
90
+
91
+ - source campaign ID, or note that the A campaign was created as the source
92
+ campaign when no source campaign was provided
93
+ - source lead-list ID when supplied
94
+ - split strategy and counts when a source lead list was supplied
95
+ - duplicate/skipped lead counts when a source lead list was supplied
96
+ - A review campaign ID and split lead-list ID when supplied
97
+ - B review campaign ID and split lead-list ID when supplied
98
+ - variant difference
99
+ - `launchState: not_started` for both campaigns
@@ -46,6 +46,9 @@ allowed-tools:
46
46
  - mcp__sellable__select_campaign_cells
47
47
  - mcp__sellable__queue_campaign_cells
48
48
  - mcp__sellable__wait_for_campaign_processing
49
+ - mcp__sellable__start_prepare_campaign_messages
50
+ - mcp__sellable__get_prepare_campaign_messages_status
51
+ - mcp__sellable__cancel_prepare_campaign_messages
49
52
  - mcp__sellable__revise_message_template_and_rerun
50
53
  - mcp__sellable__update_campaign_brief
51
54
  - mcp__sellable__update_campaign
@@ -89,6 +92,18 @@ When filters are chosen, save rubrics, get filter approval, then wait for
89
92
  message-template approval before enrichment/filtering or Generate Message cells.
90
93
  After filter approval, Filter Leads should show `Filters saved + waiting for
91
94
  message approval` until the template is approved.
95
+ After message approval, use `start_prepare_campaign_messages` for target-ready
96
+ message preparation such as "prepare 100 messages, checking up to 300 rows".
97
+ Treat `campaignId` as `CampaignOffer.id`, keep the default
98
+ `approvalMode:"mark_ready"` unless the user explicitly asks to flip Approved
99
+ cells, and poll `get_prepare_campaign_messages_status` for checked rows,
100
+ prepared/approved count, target, row budget remaining, and stop reason. Low
101
+ level selector/queue tools are diagnostics and recovery only for this lane. If
102
+ the user asks to stop preparation, the target is wrong, or status shows the
103
+ wrong campaign/table, call `cancel_prepare_campaign_messages`; otherwise do not
104
+ cancel a healthy prepare run.
105
+ Never call `start_campaign` from Prepare Messages; final launch remains a
106
+ separate explicit user greenlight.
92
107
  Use Template is the default message path; AI Generated is only an explicit
93
108
  opt-out.
94
109
 
@@ -109,6 +124,22 @@ page before importing, call `list_dnc_entries`. Confirm the active workspace
109
124
  name and ID in the response before any write. This is Sellable's workspace DNC
110
125
  list used by DNC Check.
111
126
 
127
+ ## A/B Campaign Requests
128
+
129
+ If the user explicitly asks to create an A/B test, split an existing campaign
130
+ into variants, duplicate a campaign for copy testing, or compare two campaign
131
+ message approaches from the same source list, route them to
132
+ `create-ab-test` instead of improvising inside this create-campaign workflow.
133
+
134
+ Workflow/campaign table exports are decorated outputs for operator review and
135
+ debugging. They are not source lead lists for A/B splitting or campaign
136
+ duplication. Do not use `export_table_csv` from an enriched/generated campaign
137
+ table and then reimport it as leads. If the user only has a contaminated CSV,
138
+ `load_csv_linkedin_leads` strips Sellable workflow columns such as `ICP Score`,
139
+ `Passes Rubric`, `Generate Message`, `Message`, and `Approved`, but the
140
+ preferred A/B path is the dedicated `create-ab-test` workflow using
141
+ `prepare_campaign_ab_test`.
142
+
112
143
  ## Opening Turn Contract
113
144
 
114
145
  On the first visible response after this skill is invoked, do not narrate
@@ -939,7 +970,8 @@ updates.
939
970
  observation state,
940
971
  `auto-execute-messaging` after at least one row passes and initial campaign-row
941
972
  messages are being generated or reviewed, `awaiting-user-greenlight` only
942
- after generated campaign-row messages are approved, `settings` for sender
973
+ after generated campaign-row messages are approved and the Prepare Messages
974
+ job has reported compact checked/prepared/stop status, `settings` for sender
943
975
  selection, `sequence` after sender attach, and `send` once the recommended
944
976
  sequence is attached. Do not advance the step backward.
945
977
  7. Keep `selectedLeadListId` as the source list and `workflowTableId` as the