@sellable/mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/.claude-plugin/plugin.json +12 -0
  2. package/.mcp.json +9 -0
  3. package/README.md +355 -0
  4. package/dist/api.d.ts +21 -0
  5. package/dist/api.js +73 -0
  6. package/dist/auth.d.ts +60 -0
  7. package/dist/auth.js +246 -0
  8. package/dist/engage-memory.d.ts +63 -0
  9. package/dist/engage-memory.js +354 -0
  10. package/dist/index-dev.d.ts +2 -0
  11. package/dist/index-dev.js +17 -0
  12. package/dist/index.d.ts +7 -0
  13. package/dist/index.js +8 -0
  14. package/dist/server.d.ts +1 -0
  15. package/dist/server.js +499 -0
  16. package/dist/skills.d.ts +11 -0
  17. package/dist/skills.js +97 -0
  18. package/dist/tools/auth.d.ts +30 -0
  19. package/dist/tools/auth.js +124 -0
  20. package/dist/tools/blueprint-commit.d.ts +174 -0
  21. package/dist/tools/blueprint-commit.js +286 -0
  22. package/dist/tools/bootstrap.d.ts +64 -0
  23. package/dist/tools/bootstrap.js +246 -0
  24. package/dist/tools/campaigns.d.ts +589 -0
  25. package/dist/tools/campaigns.js +892 -0
  26. package/dist/tools/cells.d.ts +58 -0
  27. package/dist/tools/cells.js +48 -0
  28. package/dist/tools/context.d.ts +88 -0
  29. package/dist/tools/context.js +271 -0
  30. package/dist/tools/csv-domains.d.ts +73 -0
  31. package/dist/tools/csv-domains.js +464 -0
  32. package/dist/tools/csv-linkedin.d.ts +102 -0
  33. package/dist/tools/csv-linkedin.js +712 -0
  34. package/dist/tools/direct-campaigns.d.ts +240 -0
  35. package/dist/tools/direct-campaigns.js +250 -0
  36. package/dist/tools/engage-bootstrap.d.ts +94 -0
  37. package/dist/tools/engage-bootstrap.js +205 -0
  38. package/dist/tools/engage-discovery.d.ts +78 -0
  39. package/dist/tools/engage-discovery.js +150 -0
  40. package/dist/tools/engage-memory.d.ts +181 -0
  41. package/dist/tools/engage-memory.js +143 -0
  42. package/dist/tools/engage-state.d.ts +72 -0
  43. package/dist/tools/engage-state.js +62 -0
  44. package/dist/tools/enrichment.d.ts +167 -0
  45. package/dist/tools/enrichment.js +174 -0
  46. package/dist/tools/flow-preflight.d.ts +68 -0
  47. package/dist/tools/flow-preflight.js +138 -0
  48. package/dist/tools/framework.d.ts +44 -0
  49. package/dist/tools/framework.js +153 -0
  50. package/dist/tools/interaction-mode.d.ts +27 -0
  51. package/dist/tools/interaction-mode.js +102 -0
  52. package/dist/tools/leads.d.ts +2417 -0
  53. package/dist/tools/leads.js +2307 -0
  54. package/dist/tools/linkedin.d.ts +210 -0
  55. package/dist/tools/linkedin.js +229 -0
  56. package/dist/tools/navigation.d.ts +91 -0
  57. package/dist/tools/navigation.js +381 -0
  58. package/dist/tools/one-off.d.ts +229 -0
  59. package/dist/tools/one-off.js +273 -0
  60. package/dist/tools/processing.d.ts +70 -0
  61. package/dist/tools/processing.js +56 -0
  62. package/dist/tools/prompts.d.ts +211 -0
  63. package/dist/tools/prompts.js +210 -0
  64. package/dist/tools/provider-preflight.d.ts +21 -0
  65. package/dist/tools/provider-preflight.js +59 -0
  66. package/dist/tools/readiness.d.ts +261 -0
  67. package/dist/tools/readiness.js +510 -0
  68. package/dist/tools/rows.d.ts +126 -0
  69. package/dist/tools/rows.js +105 -0
  70. package/dist/tools/rubrics.d.ts +497 -0
  71. package/dist/tools/rubrics.js +681 -0
  72. package/dist/tools/senders.d.ts +44 -0
  73. package/dist/tools/senders.js +69 -0
  74. package/dist/tools/sequencer.d.ts +127 -0
  75. package/dist/tools/sequencer.js +194 -0
  76. package/dist/tools/tables.d.ts +35 -0
  77. package/dist/tools/tables.js +36 -0
  78. package/dist/tools/verify-row.d.ts +36 -0
  79. package/dist/tools/verify-row.js +38 -0
  80. package/dist/tools/workspaces.d.ts +140 -0
  81. package/dist/tools/workspaces.js +139 -0
  82. package/dist/utils/workspace-root.d.ts +1 -0
  83. package/dist/utils/workspace-root.js +39 -0
  84. package/package.json +46 -0
  85. package/skills/building-gtm-tables/SKILL.md +216 -0
  86. package/skills/building-gtm-tables/core/auto-execute.yaml +19 -0
  87. package/skills/building-gtm-tables/core/blueprint-schema.json +72 -0
  88. package/skills/building-gtm-tables/references/brief-to-blueprint.md +334 -0
  89. package/skills/building-gtm-tables/references/column-type-catalog.md +318 -0
  90. package/skills/building-gtm-tables/references/common-blueprints.fixtures.ts +199 -0
  91. package/skills/building-gtm-tables/references/common-blueprints.md +44 -0
  92. package/skills/building-gtm-tables/references/failure-taxonomy.md +197 -0
  93. package/skills/building-gtm-tables/references/uat-seed-prompts.md +37 -0
  94. package/skills/building-gtm-tables/references/verify-loop.md +74 -0
  95. package/skills/campaign-messages/SKILL.md +173 -0
  96. package/skills/campaign-messages/flow.v1.json +75 -0
  97. package/skills/craft-message/SKILL.md +401 -0
  98. package/skills/create-campaign/ARCHITECTURE.md +232 -0
  99. package/skills/create-campaign/DISCUSS.md +296 -0
  100. package/skills/create-campaign/FLOW_ASCII.md +240 -0
  101. package/skills/create-campaign/HOST-PARITY-CHECKLIST.md +49 -0
  102. package/skills/create-campaign/README.md +142 -0
  103. package/skills/create-campaign/SKILL.md +286 -0
  104. package/skills/create-campaign/context/README.md +67 -0
  105. package/skills/create-campaign/context/_TEMPLATE.md +12 -0
  106. package/skills/create-campaign/context/context.md +35 -0
  107. package/skills/create-campaign/context/learnings.md +16 -0
  108. package/skills/create-campaign/context/registry.json +19 -0
  109. package/skills/create-campaign/core/flow.v1.json +217 -0
  110. package/skills/create-campaign/core/policy.md +191 -0
  111. package/skills/create-campaign/core/providers/apollo.json +35 -0
  112. package/skills/create-campaign/core/providers/prospeo.json +34 -0
  113. package/skills/create-campaign/core/providers/registry.json +31 -0
  114. package/skills/create-campaign/core/providers/sales-nav.json +37 -0
  115. package/skills/create-campaign/core/providers/signal-discovery.json +42 -0
  116. package/skills/create-campaign/references/brief-template.md +64 -0
  117. package/skills/create-campaign/references/campaign-quality.md +84 -0
  118. package/skills/create-campaign/references/copy-calibration-examples.md +120 -0
  119. package/skills/create-campaign/references/offer-patterns.md +108 -0
  120. package/skills/create-campaign/references/provider-selection-strategy.md +212 -0
  121. package/skills/create-campaign/references/question-examples.md +167 -0
  122. package/skills/create-campaign/references/token-fill-examples.md +81 -0
  123. package/skills/create-campaign-brief/ARCHITECTURE.md +72 -0
  124. package/skills/create-campaign-brief/DISCUSS.md +64 -0
  125. package/skills/create-campaign-brief/README.md +176 -0
  126. package/skills/create-campaign-brief/SKILL.md +537 -0
  127. package/skills/create-campaign-brief/references/brief-synthesis-rules.md +100 -0
  128. package/skills/create-campaign-brief/references/brief-template.md +220 -0
  129. package/skills/create-campaign-brief/references/campaign-idea-options.md +30 -0
  130. package/skills/create-campaign-brief/references/copy-appendix-template.md +62 -0
  131. package/skills/create-campaign-brief/references/draft-lifecycle.md +23 -0
  132. package/skills/create-campaign-brief/references/examples/MANIFEST.json +89 -0
  133. package/skills/create-campaign-brief/references/examples/briefs/clover.md +223 -0
  134. package/skills/create-campaign-brief/references/examples/briefs/galley.md +222 -0
  135. package/skills/create-campaign-brief/references/examples/briefs/gelee.md +220 -0
  136. package/skills/create-campaign-brief/references/examples/briefs/hey-digital.md +234 -0
  137. package/skills/create-campaign-brief/references/examples/briefs/persona.md +231 -0
  138. package/skills/create-campaign-brief/references/examples/briefs/revvix.md +220 -0
  139. package/skills/create-campaign-brief/references/examples/briefs/sellable-dev.md +220 -0
  140. package/skills/create-campaign-brief/references/examples/briefs/superposition.md +233 -0
  141. package/skills/create-campaign-brief/references/examples/briefs/superpower.md +219 -0
  142. package/skills/create-campaign-brief/references/examples/briefs/westpark-villas.md +220 -0
  143. package/skills/create-campaign-brief/references/icp-lock-question-bank.md +43 -0
  144. package/skills/create-campaign-brief/references/messaging-inputs.md +58 -0
  145. package/skills/create-campaign-brief/references/output-acceptance-rubric.md +62 -0
  146. package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +248 -0
  147. package/skills/create-campaign-brief/references/phase75-canonical-brief-template.md +319 -0
  148. package/skills/create-campaign-brief/references/phase75-good-brief-and-messaging-examples.md +445 -0
  149. package/skills/create-campaign-brief/references/quick-research-protocol.md +39 -0
  150. package/skills/create-campaign-brief/references/reference-sheet-protocol.md +60 -0
  151. package/skills/create-campaign-brief/references/zero-shot-iteration-rules.md +66 -0
  152. package/skills/create-campaign-v2/SKILL.md +1619 -0
  153. package/skills/create-campaign-v2/core/auto-execute.README.md +219 -0
  154. package/skills/create-campaign-v2/core/auto-execute.yaml +121 -0
  155. package/skills/create-campaign-v2/core/flow.v2.json +1643 -0
  156. package/skills/create-campaign-v2/core/policy.md +82 -0
  157. package/skills/create-campaign-v2/references/ai-tells.md +253 -0
  158. package/skills/create-campaign-v2/references/approval-gate-framing.md +346 -0
  159. package/skills/create-campaign-v2/references/draft-lifecycle.md +110 -0
  160. package/skills/create-campaign-v2/references/escalation-ladder.md +119 -0
  161. package/skills/create-campaign-v2/references/filter-leads.md +495 -0
  162. package/skills/create-campaign-v2/references/final-handoff-contract.md +176 -0
  163. package/skills/create-campaign-v2/references/gold-standard-message-examples.md +394 -0
  164. package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +314 -0
  165. package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +212 -0
  166. package/skills/create-campaign-v2/references/lead-validation-preview.md +172 -0
  167. package/skills/create-campaign-v2/references/parallel-critique-protocol.md +368 -0
  168. package/skills/create-campaign-v2/references/sample-validation-loop.md +289 -0
  169. package/skills/create-campaign-v2/references/step-13-import-leads.md +151 -0
  170. package/skills/create-campaign-v2/references/step-15-re-cascade.md +90 -0
  171. package/skills/create-campaign-v2/references/thomas-revision-filters.md +521 -0
  172. package/skills/create-campaign-v2/references/thomas-variant-selection.md +202 -0
  173. package/skills/create-campaign-v2/references/tier-routing-matrix.md +66 -0
  174. package/skills/create-campaign-v2/references/validation-criteria.md +367 -0
  175. package/skills/create-campaign-v2/references/watch-link-handoff.md +106 -0
  176. package/skills/create-campaign-v2-validation/SKILL.md +296 -0
  177. package/skills/create-post/SKILL.md +1308 -0
  178. package/skills/create-rubric/SKILL.md +251 -0
  179. package/skills/engage/SKILL.md +549 -0
  180. package/skills/engage/core/README.md +23 -0
  181. package/skills/engage/core/proven-searches.json +11 -0
  182. package/skills/engage/core/style-guide.template.md +47 -0
  183. package/skills/engage/core/tracked-people.json +10 -0
  184. package/skills/enrich-prospects/SKILL.md +97 -0
  185. package/skills/find-leads/SKILL.md +467 -0
  186. package/skills/generate-messages/SKILL.md +2361 -0
  187. package/skills/interview/SKILL.md +132 -0
  188. package/skills/interview/core/ENGAGE_STYLE_GUIDE.template.md +54 -0
  189. package/skills/interview/core/ICP.template.md +54 -0
  190. package/skills/interview/core/VOICE_PROFILE.template.md +101 -0
  191. package/skills/providers/apollo.md +520 -0
  192. package/skills/providers/prospeo.md +398 -0
  193. package/skills/providers/sales-nav.md +372 -0
  194. package/skills/providers/signal-discovery.md +495 -0
  195. package/skills/research/SKILL.md +258 -0
  196. package/skills/research/config.json +9 -0
  197. package/skills/research/override.md +13 -0
  198. package/skills/research-prospect/SKILL.md +99 -0
  199. package/skills/research-sender/SKILL.md +158 -0
  200. package/skills/workflow-sequences/SKILL.md +85 -0
@@ -0,0 +1,286 @@
1
+ ---
2
+ name: create-campaign
3
+ description: Guide a user through creating a LinkedIn outbound campaign with profile enrichment, sender research, JTBD positioning, lead sourcing, and ICP filtering. Use when starting a fresh campaign or resuming an existing one (cmp_... ID). Handles provider selection, brief generation, and lead import with watch-mode UI orientation.
4
+ visibility: internal
5
+ ---
6
+
7
+ # Create Campaign (Legacy)
8
+
9
+ Legacy internal workflow kept for compatibility with older direct MCP callers.
10
+ The public `sellable:create-campaign` skill now loads the approval-gated
11
+ `create-campaign-v2` workflow.
12
+
13
+ You are a LinkedIn Outbound Expert specializing in booking meetings for B2B companies. Craft simple, conversational outreach that gets busy executives to respond.
14
+
15
+ **Data integrity rule**: Never hallucinate or make up social proof, reviews, case studies, or success metrics. Only use data from context or explicitly provided by the user. If missing, mark as "Not provided" -- never invent placeholders.
16
+
17
+ **Objective**: Create a LinkedIn outbound campaign through guided discovery: enrich profile, gather positioning via AskUserQuestion, draft a JTBD-based campaign angle, create campaign with brief, and hand off to lead sourcing. Campaign created with positioning, brief saved, user ready for leads.
18
+
19
+ ## Bootstrap
20
+
21
+ 1. Load tools (SINGLE message with ToolSearch calls):
22
+ - `ToolSearch("select:mcp__sellable__enrich_sender")`
23
+ - `ToolSearch("select:mcp__sellable__create_campaign")`
24
+ - `ToolSearch("select:mcp__sellable__update_campaign")`
25
+ - `ToolSearch("select:mcp__sellable__update_campaign_brief")`
26
+ - `ToolSearch("select:mcp__sellable__bootstrap_create_campaign")`
27
+ - `ToolSearch("select:mcp__sellable__get_campaign_context")`
28
+ - `ToolSearch("select:mcp__sellable__get_auth_status")`
29
+ - `ToolSearch("select:mcp__sellable__wait_for_lead_list_ready")`
30
+ - `ToolSearch("select:mcp__sellable__wait_for_campaign_table_ready")`
31
+ - `ToolSearch("select:mcp__sellable__get_rows_minimal")`
32
+ - `ToolSearch("select:mcp__sellable__list_subskill_prompts")`
33
+ - `ToolSearch("select:mcp__sellable__get_subskill_prompt")`
34
+ - `ToolSearch("select:mcp__sellable__search_subskill_prompts")`
35
+ - `ToolSearch("select:mcp__sellable__complete_sender_research")`
36
+ 2. Detect optional campaign ID (pattern: `cmp_...`).
37
+ 3. Resume boundary (STRICT):
38
+ - No campaignId from user -> stay in fresh-create mode.
39
+ - Do NOT call `get_campaigns` or `get_campaign` to hunt for IDs.
40
+ - Do NOT call `create_campaign({ campaignId: ... })` unless that exact ID came from user input.
41
+ 4. Call `bootstrap_create_campaign({ campaignId? })`.
42
+ 5. If `safeToProceed !== true`: STOP. Show `blockingErrors` and `nextStep`. Fail-fast: `Bootstrap incomplete. Resolve blockingErrors and rerun bootstrap_create_campaign before provider/search/import tools.`
43
+ 6. Continue only when preflight passes.
44
+ 7. Bootstrap no longer returns skill prompt or policy prose (both loaded via host). `framework.policy` = `"[loaded via host skill prompt]"`.
45
+ 8. Load framework and obey: `framework.flow`, `framework.providerRegistry`, `framework.providers`, `framework.plugins`, `framework.overrides`.
46
+ 9. Resume-first when campaignId provided: call `create_campaign({ campaignId })` for watchUrl, then `get_campaign_context({ campaignId, refresh: true })`. Use `context.navState` + `framework.flow` to decide next step.
47
+ 10. Do NOT load `get_linkedin_profile` -- use `enrich_sender` instead.
48
+ 11. Do NOT load `.sellable/` config files at bootstrap -- other skills load them when relevant.
49
+ 12. Check if user provided context (LinkedIn URL, company info, or campaign direction).
50
+ 13. Workspace + LinkedIn URL (REQUIRED after bootstrap):
51
+ - If bootstrap succeeded: state workspace as fact and ask for LinkedIn URL in one message. Example: "Starting a campaign in **{workspaceName}**. What's your LinkedIn URL? I'll pull your background, company info, and proof points to build the positioning."
52
+ - If bootstrap failed with `error.type: "workspace"` (no active workspace): follow the `blockingErrors` guidance -- call `list_workspaces` to show available workspaces, then `set_active_workspace` with the user's choice. Re-run `bootstrap_create_campaign` after workspace is set.
53
+ 14. If user already provided LinkedIn URL or context, still state the workspace but skip the URL ask.
54
+
55
+ **Phase 5 tools (load after provider selection):**
56
+
57
+ - `ToolSearch("select:mcp__sellable__get_provider_prompt")` -- REQUIRED preflight gate
58
+ - `ToolSearch("select:mcp__sellable__search_apollo")` OR `search_sales_nav` OR `search_signals` -- based on provider
59
+ - `ToolSearch("select:mcp__sellable__import_leads")`
60
+ - `ToolSearch("select:mcp__sellable__confirm_lead_list")`
61
+ - `ToolSearch("select:mcp__sellable__wait_for_lead_list_ready")`
62
+ - `ToolSearch("select:mcp__sellable__load_csv_linkedin_leads")`
63
+
64
+ ## Tools
65
+
66
+ **Framework + Plugins**: `bootstrap_create_campaign` (returns auth + framework + subskill catalog), `get_campaign_context`, `list_subskill_prompts`. `get_campaign_framework` only if bootstrap didn't return framework.
67
+ **Enrichment**: `enrich_sender` (CALL FIRST -- returns clientProspectId)
68
+ **Research**: `get_subskill_prompt({ subskillName: "research-sender" })` -- dedicated protocol, not generic `research`
69
+ **Campaign**: `create_campaign`, `update_campaign`, `update_campaign_brief`
70
+ **Lead Sourcing**: `get_provider_prompt` (CALL FIRST for provider), `search_apollo`, `search_sales_nav`, `search_signals`, `load_csv_domains`, `load_csv_linkedin_leads`, `import_leads`, `confirm_lead_list`, `wait_for_lead_list_ready`, `wait_for_campaign_table_ready`, `get_rows_minimal`
71
+ **Questions**: `AskUserQuestion` -- max 4 questions per call, 2-4 options each
72
+ **Chrome (debug only)**: `read_page`, `get_page_text` -- use only when user reports "I don't see it"
73
+
74
+ ## Phase 0: Apply Framework (from bootstrap)
75
+
76
+ Bootstrap already returned the full framework. Do NOT call `get_campaign_framework` again -- use `bootstrap.framework` directly. Only call `get_campaign_framework` if bootstrap didn't return it (e.g., framework check failed and was retried).
77
+
78
+ Apply overrides:
79
+
80
+ - `providerOrder = overrides.providerOrder || providerRegistry.defaultProviderOrder`
81
+ - `providerPreference = overrides.providerPreference || null`
82
+ - `defaultLeadTarget = overrides.defaultLeadTarget || providerMaxImportCount`
83
+ - `providerMaxImportCount` from `lead-import-limits.json` (active provider's `maxImportCount`; default 250)
84
+
85
+ Subskill handoff: if a flow step includes `action: "handoff_to_subskill"`, call `get_subskill_prompt({ subskillName: action.target })` and follow immediately.
86
+
87
+ Review `framework.plugins` and incorporate factual constraints. If warnings, summarize briefly and continue.
88
+
89
+ **Watch mode**: After every `update_campaign({ currentStep: ... })`, say what changed, tell user what to expect in watch link. In `step-by-step` mode pause for confirmation; in `ask-when-needed`/`autonomous` continue unless a required user choice is missing. Check `navigation.blockedAt` and `navigation.missing` after each step change.
90
+
91
+ ## Phase 1: Initial Discovery
92
+
93
+ ### Step 1: Enrich Sender (REQUIRED)
94
+
95
+ 1. Narrate: "Enriching your LinkedIn profile..."
96
+ 2. Call `enrich_sender` with LinkedIn URL without `forceRefresh` (cache-first, compact mode default)
97
+ 3. GATE: Store `clientProspectId` from response -- hard stop if missing
98
+ 4. Extract: `clientProspectId`, `sender` (fullName, headline, title, company), `companyDomain`
99
+ 5. When `enrichmentStatus === "complete"`, also extract `companySnapshot`, `senderBackground`, `proofDigest`
100
+
101
+ ### Step 2: Confirm Company (REQUIRED)
102
+
103
+ GATE: Do NOT start research until the campaign company/domain is confirmed.
104
+
105
+ AskUserQuestion: "Yes, research this" / "Different company" (see `references/question-examples.md` for JSON shape).
106
+
107
+ If "Different company": ask for domain, re-confirm before proceeding.
108
+
109
+ ### Step 3: Research Depth Decision
110
+
111
+ - `proofDigest.caseStudyCount > 0` AND `proofDigest.reviewHighlight` exists -> `minimal-verification` (0 agents, ~2s)
112
+ - Otherwise -> `deep-proof` (2 agents in parallel, ~30s)
113
+
114
+ ### Step 4: Run Sender Research Subskill
115
+
116
+ Send progress note: "Running a quick research pass for case studies and growth signals (~30s)..."
117
+
118
+ 1. Call `get_subskill_prompt({ subskillName: "research-sender" })`
119
+ 2. Follow instructions directly -- do NOT delegate to generic `research`
120
+ 3. Pass full `enrich_sender` response as `enrichSender` input
121
+ 4. GATE: `complete_sender_research` must finish before `create_campaign`
122
+ 5. Proof rule: use research if stronger, keep enrichment if not, never fabricate
123
+
124
+ **If no URL provided:** Ask for LinkedIn profile URL.
125
+
126
+ ## Phase 2: Confirm Scope
127
+
128
+ After confirmation + research, single AskUserQuestion anchored to companyDomain: "Draft one for me" / "I have an idea" / "Different company/offer" (see `references/question-examples.md`).
129
+
130
+ - "I have an idea" -> ask for target + angle in 1-2 sentences
131
+ - "Different company/offer" -> ask for correct domain + description, re-run enrichment + research
132
+ - "Draft one for me" -> proceed to Phase 3
133
+
134
+ ## Phase 3: Draft Campaign Angle
135
+
136
+ Draft ONE JTBD-based angle using sender research + user input + configs.
137
+
138
+ Leverage configs if loaded: `icp.md` for Target, `cross-skill.md` for messaging insights, `outbound.md` for structure.
139
+
140
+ Default format: Target / Pain / Offer / Proof (if provided).
141
+
142
+ GATE: Ask "Want me to use this, or tweak anything?" -- wait for approval.
143
+
144
+ For quality patterns, Read `references/campaign-quality.md`.
145
+
146
+ ## Phase 4: Create Campaign
147
+
148
+ ### Step 1: Create
149
+
150
+ Call `create_campaign({ name, clientProspectId, campaignBrief })`.
151
+
152
+ - GATE: `clientProspectId` MUST come from Phase 1 `enrich_sender`. If missing, call `enrich_sender` first.
153
+ - For brief format, Read `references/brief-template.md`.
154
+
155
+ ### Step 2: Show Watch Link
156
+
157
+ "Campaign created! **Watch link:** [watchUrl]. Open to see your campaign brief."
158
+ GATE: Wait for user confirmation before proceeding.
159
+
160
+ ### Step 3: Set Execution Mode
161
+
162
+ Explain interaction modes, then AskUserQuestion: step-by-step (Recommended) / use best judgment / ask when needed.
163
+ Store as `interactionMode`: `step-by-step` / `autonomous` / `ask-when-needed`.
164
+ Default `ask-when-needed` if ambiguous. (See `references/question-examples.md` for preface + JSON.)
165
+
166
+ ## Phase 5: Lead Provider Selection
167
+
168
+ Execution by `interactionMode`:
169
+
170
+ - `step-by-step`: pause for provider choice, import, confirm. After choice confirmed, run preflight + search immediately.
171
+ - `autonomous`: proceed with best judgment unless a required decision is missing.
172
+ - `ask-when-needed`: skip repetitive confirmations, pause only for high-impact branches.
173
+
174
+ ### Step 1: Update Step
175
+
176
+ `update_campaign({ campaignId, currentStep: "pick-provider" })`. Orient user.
177
+
178
+ ### Step 2: Recommend Provider
179
+
180
+ Analyze ICP against `framework.providers[*].recommendation` fields and `recommendation.prose` template.
181
+ For detailed decision logic, Read `references/provider-selection-strategy.md`.
182
+ Build AskUserQuestion from `providerOrder` + `askOption` (not hardcoded).
183
+ GATE: User selects provider.
184
+
185
+ ### Step 3: Normalize Selection
186
+
187
+ Store `labelToProviderId` map, resolve `providerId`. Load `providerConfig = framework.providers[providerId]`. Fallback: first valid provider in `providerOrder`.
188
+
189
+ ### Step 4: Update Campaign Step
190
+
191
+ `update_campaign({ campaignId, currentStep: providerConfig.currentStep, leadSourceProvider: providerConfig.leadSourceProvider })`. Orient user with `providerConfig.watch.stepVisible`.
192
+
193
+ ### Step 5: Provider Preflight
194
+
195
+ GATE: If `providerConfig.promptProvider` exists, MUST call `get_provider_prompt({ provider: providerConfig.promptProvider, confirmed: true })` BEFORE any search.
196
+ If `promptProvider` is null: manual branch -- tell user to upload list in UI, wait for confirmation, proceed to Phase 6.
197
+
198
+ ### Step 6: Execute Search
199
+
200
+ Follow provider prompt instructions for search workflow.
201
+
202
+ If the user already has a CSV on disk:
203
+
204
+ - LinkedIn profile CSV: use `load_csv_linkedin_leads` instead of provider search + `import_leads`
205
+ - Company-domain CSV: use `load_csv_domains`, then continue with provider search using the returned `domainFilterId`
206
+
207
+ ### Step 7: Import and Wait
208
+
209
+ 1. Call `import_leads`.
210
+ 2. If `needsModeSelection: true`: GATE -- AskUserQuestion add/replace. Do NOT assume. Re-call `import_leads` with user's choice.
211
+ 3. Call `wait_for_lead_list_ready({ campaignOfferId, jobId, targetLeadCount })`.
212
+ GATE: Handle each `ready: false` reason:
213
+ - `cancelled`: the operator cancelled this import; restart with tighter filters if needed
214
+ - `import_failed` / `stalled_import`: tell user, ask to retry
215
+ - `tool_timeout_guard` / `timeout`: tell user polling timed out, re-run wait
216
+ - `missing_job_id`: ask for ID
217
+ - NEVER say "running successfully" unless `ready: true`
218
+
219
+ ### Cancelling and restarting mid-import
220
+
221
+ If the operator realizes the active filter is wrong while an import is in flight, call `cancel_lead_import` with `{ campaignOfferId, tableId, provider }`. All three fields are required; there is no auto-detect. Pass the provider from the active campaign context.
222
+
223
+ Partial rows are preserved. Provider credits are not refunded. After cancel, call `import_leads` again with the new filters. `wait_for_lead_list_ready` returns `{ ready: false, reason: "cancelled" }` for the old import until the new one starts.
224
+
225
+ Supported in this phase: `apollo`, `prospeo`, and `sales-nav`. Signal Discovery cancel is tracked in a follow-on phase.
226
+
227
+ ### Step 8: User Reviews Lead List (HARD STOP)
228
+
229
+ **GATE: Do NOT call `confirm_lead_list` until the user explicitly confirms.**
230
+
231
+ Orient user: "[X] leads found. Review the lead list in the watch link and let me know when it looks good."
232
+
233
+ STOP HERE. Wait for user to say "looks good", "confirmed", "yes", etc. This gate applies in ALL modes including `autonomous`. The user must review the list before it gets imported into the campaign table.
234
+
235
+ ### Step 9: Confirm and Post-Import
236
+
237
+ Only after user confirms:
238
+
239
+ 1. Call `confirm_lead_list({ campaignOfferId, jobId, targetLeadCount })`. Narrate: "Importing leads into your campaign table..."
240
+ 2. `update_campaign({ campaignId, currentStep: "filter-choice" })`.
241
+ 3. `wait_for_campaign_table_ready({ campaignId })` -- GATE: must be `ready: true`.
242
+ 4. `get_campaign_context({ campaignId, refresh: true })`.
243
+ 5. `get_rows_minimal({ tableId: workflowTableId, limit: 10, page: 1 })`.
244
+ 6. Filter recommendation: compare sample to ICP. Pick Add filters / Skip filters / Refine list first. Warn if list is small (<150) or ICP already narrow.
245
+
246
+ ## Phase 6: Hand Off
247
+
248
+ **If "add filters":**
249
+
250
+ - `update_campaign({ campaignId, currentStep: "filter-rules" })`
251
+ - Do NOT set `enableICPFilters: true` yet
252
+ - Hand off to `create-rubric` via `get_subskill_prompt`
253
+
254
+ **If "skip filters":**
255
+
256
+ - `update_campaign({ campaignId, currentStep: "messages", enableICPFilters: false, useMessagingTemplate: false })`
257
+ - `get_campaign_context({ campaignId, refresh: true })` + `get_rows_minimal({ tableId: workflowTableId, limit: 5 })`
258
+ - Show lead preview, offer to draft first message
259
+
260
+ **Debug**: If user reports missing content, use `read_page({ filter: "interactive" })`.
261
+
262
+ ## Rules
263
+
264
+ 1. Never hallucinate social proof -- mark "Not provided"
265
+ 2. JTBD framework -- tasks on their TODO list today
266
+ 3. Single best meeting value -- ONE offer
267
+ 4. Title format: "[Meeting Value] for [Target Audience]"
268
+ 5. No emojis. Bold sparingly.
269
+ 6. Max 1-2 questions per phase
270
+ 7. Auto-proceed on affirmatives: yes/looks good/continue/ok/sure/ready/next/go ahead/let's go
271
+ 8. Narrate progress: "Enriching your profile...", "Creating campaign..."
272
+ 9. Never use WebSearch more than once in a row
273
+ 10. Believable transformations (15-30%, not 10x)
274
+ 11. Blank lines between thoughts. Max 2-3 sentences per paragraph.
275
+ 12. Social proof = user's answer verbatim
276
+ 13. Subskills via `get_subskill_prompt` only, never as slash commands
277
+ 14. Chrome tools for debugging only (user reports "I don't see it")
278
+
279
+ ## References
280
+
281
+ | File | Load when |
282
+ | ------------------------------------------- | -------------------------------------------- |
283
+ | `references/provider-selection-strategy.md` | Phase 5, before recommending provider |
284
+ | `references/brief-template.md` | Phase 4, when writing campaign brief |
285
+ | `references/campaign-quality.md` | Phase 3, when drafting campaign angle |
286
+ | `references/question-examples.md` | Any phase, for AskUserQuestion JSON examples |
@@ -0,0 +1,67 @@
1
+ # Create Campaign Customization
2
+
3
+ This folder is the safe place to add context and defaults without editing `SKILL.md`.
4
+
5
+ ## How it works
6
+
7
+ - `context/registry.json` is the source of truth.
8
+ - The registry currently uses a `plugins` array; treat each item as a context entry.
9
+ - The MCP tool `get_campaign_framework` loads every enabled entry listed there.
10
+ - Each entry can contribute:
11
+ - Freeform context (from the file)
12
+ - Structured overrides (from the registry entry)
13
+
14
+ ## File responsibilities
15
+
16
+ - `context.md`
17
+ - Organization-wide truths and hard constraints
18
+ - Brand voice rules that should apply broadly
19
+ - Compliance or proof restrictions
20
+ - No campaign-specific examples or draft copy
21
+ - `learnings.md`
22
+ - Short, factual notes from observed campaign outcomes
23
+ - What worked, what failed, what converted better
24
+ - No aspirational advice or invented numbers
25
+ - `references/*.md`
26
+ - Reusable examples, contrastive good/bad patterns, and prompt inspiration
27
+ - Offer structures, token-fill examples, calibration examples
28
+ - This is where "what good looks like" should live, not in `context.md`
29
+
30
+ ## Add a new context file
31
+
32
+ 1. Copy `_TEMPLATE.md` to a new file in this folder.
33
+ 2. Add an entry to `context/registry.json` with `enabled: true`.
34
+ 3. (Optional) Add overrides in the registry entry.
35
+
36
+ ## Overrides (registry.json)
37
+
38
+ Use overrides to adjust deterministic behavior:
39
+
40
+ ```json
41
+ {
42
+ "overrides": {
43
+ "providerPreference": "sales-nav",
44
+ "providerOrder": ["sales-nav", "apollo", "signal-discovery"],
45
+ "defaultLeadTarget": 250,
46
+ "researchMode": "user-directed",
47
+ "researchNotes": "Always start with Sales Nav + posted recently"
48
+ }
49
+ }
50
+ ```
51
+
52
+ Prefer leaving `defaultLeadTarget` unset so the provider max from `lead-import-limits.json`
53
+ is used automatically.
54
+
55
+ ## Learning log
56
+
57
+ Add short, factual notes to `learnings.md`. It is loaded automatically.
58
+
59
+ When adding examples:
60
+
61
+ - Put organization-wide truths in `context.md`
62
+ - Put observed outcomes in `learnings.md`
63
+ - Put reusable prompt examples in:
64
+ - `references/campaign-quality.md`
65
+ - `references/offer-patterns.md`
66
+ - `references/token-fill-examples.md`
67
+ - `references/copy-calibration-examples.md`
@@ -0,0 +1,12 @@
1
+ # Context File: <name>
2
+
3
+ Describe any context that should shape campaign creation.
4
+
5
+ ## What this plugin changes
6
+
7
+ - Example: prefer Sales Navigator for enterprise ICPs
8
+ - Example: exclude healthcare and government
9
+
10
+ ## Evidence-backed notes only
11
+
12
+ Do not add claims unless they are true and supported.
@@ -0,0 +1,35 @@
1
+ # Campaign Context
2
+
3
+ Use this file for organization-wide truths that should influence every campaign.
4
+
5
+ ## Global Rules
6
+
7
+ - Clear over clever.
8
+ - Use only real proof, logos, testimonials, or metrics that came from the client or trusted research.
9
+ - If proof is thin, surface it as an open question instead of filling the gap with generic claims.
10
+ - Default to 5th-grade readability unless the buyer, industry, or cited material clearly requires more technical language.
11
+ - Messages should sound like a human peer, not a landing page or an AI writing assistant.
12
+ - Imperfection is acceptable when it improves naturalness. Polished does not mean sterile.
13
+
14
+ ## Offer Constraints
15
+
16
+ - Prefer low-friction offers that give value before asking for time.
17
+ - Avoid generic "free audit", "free assessment", or framework-named offers unless the deliverable is concrete and differentiated.
18
+ - If the prospect has only shown mild interest, the next ask should usually be easier than booking a meeting.
19
+
20
+ ## Proof Discipline
21
+
22
+ - Named proof beats vague credibility claims.
23
+ - Use the client's own words, customer language, and concrete product specifics when available.
24
+ - Never overstate transformations or invent quantitative outcomes.
25
+
26
+ ## Scope
27
+
28
+ Good contents for this file:
29
+
30
+ - Compliance constraints
31
+ - Cross-client voice principles
32
+ - Global exclusions
33
+ - Proof rules
34
+
35
+ Do not put campaign-specific examples or calibration snippets here. Those belong in the reference docs.
@@ -0,0 +1,16 @@
1
+ # Campaign Learnings
2
+
3
+ This log captures what has worked in real campaigns.
4
+
5
+ Entries should be short, specific, and based on observed outcomes.
6
+
7
+ **Cross-skill learnings** that would help other skills (engage, create-post) should ALSO be written to `.sellable/insights/cross-skill.md` so the entire system learns.
8
+
9
+ ## Log
10
+
11
+ - 2026-01-25: Initialized learning log. Add entries manually when outcomes are observed.
12
+ - 2026-04-08: Lower-friction "send something valuable first" offers often convert warm interest better than asking for a meeting immediately.
13
+ - 2026-04-08: A/B CTA structures are useful when one option is passive or lightweight and the other is a higher-commitment path.
14
+ - 2026-04-08: 5th-grade readability and peer tone are quality constraints, not optional polish.
15
+ - 2026-04-08: Token-fill quality matters enough to warrant explicit good and bad examples; awkward interpolation can ruin otherwise strong copy.
16
+ - 2026-04-08: Positive reply rate does not guarantee meetings if the follow-up ask is too heavy for the prospect's level of intent.
@@ -0,0 +1,19 @@
1
+ {
2
+ "version": "v1",
3
+ "plugins": [
4
+ {
5
+ "id": "context",
6
+ "path": "mcp/sellable/skills/create-campaign/context/context.md",
7
+ "enabled": true,
8
+ "description": "Organization-wide truths, constraints, and messaging rules that should influence every campaign.",
9
+ "overrides": {}
10
+ },
11
+ {
12
+ "id": "learnings",
13
+ "path": "mcp/sellable/skills/create-campaign/context/learnings.md",
14
+ "enabled": true,
15
+ "description": "Observed campaign outcomes and lightweight learnings; reusable prompt examples live in references/*.md.",
16
+ "overrides": {}
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,217 @@
1
+ {
2
+ "version": "v1",
3
+ "workflow": "campaign-builder",
4
+ "principle": "State machine first, prose second",
5
+ "events": [
6
+ "campaign_created",
7
+ "user_ready_for_leads",
8
+ "provider_selected",
9
+ "provider_prompt_loaded",
10
+ "leads_imported",
11
+ "user_ready_for_rubric",
12
+ "user_filter_choice",
13
+ "user_filter_choice_add",
14
+ "user_filter_choice_skip"
15
+ ],
16
+ "steps": [
17
+ {
18
+ "id": "campaign-created",
19
+ "label": "Campaign Brief",
20
+ "onEnter": [
21
+ {
22
+ "tool": "create_campaign",
23
+ "requiredFields": ["clientProspectId", "campaignBrief"]
24
+ }
25
+ ],
26
+ "allowedTools": [
27
+ "create_campaign",
28
+ "update_campaign_brief",
29
+ "AskUserQuestion"
30
+ ],
31
+ "watchRequired": true,
32
+ "waitFor": "user_ready_for_leads",
33
+ "transitions": {
34
+ "user_ready_for_leads": "pick-provider"
35
+ }
36
+ },
37
+ {
38
+ "id": "pick-provider",
39
+ "label": "Provider Selection",
40
+ "currentStepValue": "pick-provider",
41
+ "onEnter": [
42
+ {
43
+ "tool": "update_campaign",
44
+ "requiredFields": ["campaignId", "currentStep"],
45
+ "requiredValues": {
46
+ "currentStep": "pick-provider"
47
+ }
48
+ },
49
+ {
50
+ "action": "watch_mode_orient"
51
+ }
52
+ ],
53
+ "allowedTools": [
54
+ "update_campaign",
55
+ "confirm_lead_list",
56
+ "wait_for_campaign_table_ready",
57
+ "AskUserQuestion"
58
+ ],
59
+ "watchTemplates": {
60
+ "change": "I moved you to provider selection.",
61
+ "watch": "You should see the provider selection step in the watch link now.",
62
+ "wait": "Tell me when you see it, and I will continue."
63
+ },
64
+ "waitFor": "provider_selected",
65
+ "transitions": {
66
+ "provider_selected": "provider-search"
67
+ }
68
+ },
69
+ {
70
+ "id": "provider-search",
71
+ "label": "Provider Search",
72
+ "onEnter": [
73
+ {
74
+ "tool": "update_campaign",
75
+ "requiredFields": ["campaignId", "currentStep", "leadSourceProvider"]
76
+ },
77
+ {
78
+ "action": "watch_mode_orient"
79
+ },
80
+ {
81
+ "tool": "get_provider_prompt",
82
+ "requiredFields": ["provider"]
83
+ }
84
+ ],
85
+ "allowedTools": [
86
+ "update_campaign",
87
+ "get_provider_prompt",
88
+ "search_apollo",
89
+ "search_sales_nav",
90
+ "search_prospeo",
91
+ "search_signals",
92
+ "select_promising_posts",
93
+ "set_headline_icp_criteria",
94
+ "import_leads",
95
+ "wait_for_lead_list_ready",
96
+ "cancel_lead_import",
97
+ "confirm_lead_list",
98
+ "AskUserQuestion"
99
+ ],
100
+ "watchTemplates": {
101
+ "change": "I opened the {{provider.label}} step.",
102
+ "watch": "You should now see the {{provider.label}} search UI in the watch link.",
103
+ "wait": "I will start provider preflight + search now. If the step does not look right in the watch link, tell me and I will pause to debug."
104
+ },
105
+ "waitFor": "leads_imported",
106
+ "transitions": {
107
+ "leads_imported": "confirm-lead-list"
108
+ }
109
+ },
110
+ {
111
+ "id": "confirm-lead-list",
112
+ "label": "Confirm Lead List",
113
+ "currentStepValue": "confirm-lead-list",
114
+ "onEnter": [
115
+ {
116
+ "tool": "update_campaign",
117
+ "requiredFields": ["campaignId", "currentStep"],
118
+ "requiredValues": {
119
+ "currentStep": "confirm-lead-list"
120
+ }
121
+ },
122
+ {
123
+ "action": "watch_mode_orient"
124
+ }
125
+ ],
126
+ "allowedTools": ["update_campaign", "AskUserQuestion"],
127
+ "watchTemplates": {
128
+ "change": "I moved you to the lead list confirmation step.",
129
+ "watch": "You should see the lead list we found and can confirm it looks right.",
130
+ "wait": "Tell me when it looks good, and I will move to ICP scoring."
131
+ },
132
+ "waitFor": "user_ready_for_rubric",
133
+ "transitions": {
134
+ "user_ready_for_rubric": "filter-choice"
135
+ }
136
+ },
137
+ {
138
+ "id": "filter-choice",
139
+ "label": "Enable Filtering",
140
+ "currentStepValue": "filter-choice",
141
+ "onEnter": [
142
+ {
143
+ "tool": "update_campaign",
144
+ "requiredFields": ["campaignId", "currentStep"],
145
+ "requiredValues": {
146
+ "currentStep": "filter-choice"
147
+ }
148
+ },
149
+ {
150
+ "action": "watch_mode_orient"
151
+ }
152
+ ],
153
+ "allowedTools": [
154
+ "update_campaign",
155
+ "wait_for_campaign_table_ready",
156
+ "get_campaign_context",
157
+ "get_rows_minimal",
158
+ "AskUserQuestion"
159
+ ],
160
+ "watchTemplates": {
161
+ "change": "I moved you to the Enable Filtering step.",
162
+ "watch": "You should see the yes/no choice for ICP filtering.",
163
+ "wait": "I will sample the imported leads and then ask whether you want to add filters or skip."
164
+ },
165
+ "waitFor": "user_filter_choice",
166
+ "transitions": {
167
+ "user_filter_choice_add": "handoff",
168
+ "user_filter_choice_skip": "messages-preview"
169
+ }
170
+ },
171
+ {
172
+ "id": "messages-preview",
173
+ "label": "Messages",
174
+ "currentStepValue": "messages",
175
+ "onEnter": [
176
+ {
177
+ "tool": "update_campaign",
178
+ "requiredFields": ["campaignId", "currentStep"],
179
+ "requiredValues": {
180
+ "currentStep": "messages"
181
+ }
182
+ },
183
+ {
184
+ "tool": "get_campaign_context",
185
+ "requiredFields": ["campaignId"]
186
+ },
187
+ {
188
+ "tool": "get_rows_minimal",
189
+ "requiredFields": ["tableId"]
190
+ }
191
+ ],
192
+ "allowedTools": [
193
+ "update_campaign",
194
+ "get_campaign_context",
195
+ "get_rows_minimal",
196
+ "get_table_rows",
197
+ "AskUserQuestion"
198
+ ],
199
+ "terminal": true
200
+ },
201
+ {
202
+ "id": "handoff",
203
+ "label": "Handoff to Rubric + Messages",
204
+ "onEnter": [
205
+ {
206
+ "action": "provide_watch_link"
207
+ },
208
+ {
209
+ "action": "handoff_to_subskill",
210
+ "target": "create-rubric"
211
+ }
212
+ ],
213
+ "allowedTools": ["AskUserQuestion"],
214
+ "terminal": true
215
+ }
216
+ ]
217
+ }