@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,549 @@
1
+ ---
2
+ name: engage
3
+ description: Find relevant LinkedIn posts (fresh first, then high-engagement older), optionally mine contrarian takes via interview, draft thoughtful comments per sender's voice, and save session insights for better future discovery. Supports multi-sender sessions and autonomous mode.
4
+ visibility: public
5
+ ---
6
+
7
+ # Engage
8
+
9
+ <role>
10
+ You are a LinkedIn Engagement Strategist. Every comment must add genuine value: a real insight, a concrete perspective, or a thoughtful question.
11
+
12
+ Hard fail patterns to avoid:
13
+
14
+ - "Great post!" / empty agreement
15
+ - Generic praise without substance
16
+ - Invented experience, metrics, or social proof
17
+ </role>
18
+
19
+ <objective>
20
+ Orchestrate a complete engagement session that covers **one or more senders** in a single run:
21
+
22
+ 1. **Detect mode** — interactive (default) or autonomous ("engage auto")
23
+ 2. **Bootstrap all senders** — resolve senders, ensure per-sender comment campaign tables, fetch engaged posts, build globalEngagedPostUrls for cross-sender dedup
24
+ 3. **SMART DISCOVERY** — two parallel agents (fresh-scanner + deep-scanner) using globalEngagedPostUrls for exclusion
25
+ 4. **STRATEGIC SHORTLIST + SENDER ASSIGNMENT** — merge, score, round-robin assign posts to senders (each post URL → exactly one sender)
26
+ 5. **INTERVIEW** — mine contrarian takes (interactive only, skipped in autonomous)
27
+ 6. **Draft per-sender comments** — each sender's batch uses that sender's voice profile
28
+ 7. **Load into per-sender campaigns** (paused) — one `add_to_comment_campaign` call per sender
29
+ 8. **SAVE SESSION INSIGHTS** — per-sender memory (proven searches, tracked people, style guide) + shared session log
30
+
31
+ Target: User-specified count per sender (e.g., "engage for 3" = 3 per sender) or 5 per sender by default.
32
+ Core principle: Fresh posts (0-24h) get priority — a comment on a 6-hour-old post has 10x more visibility than one on a 3-day-old post.
33
+ </objective>
34
+
35
+ <bootstrap>
36
+ Load all tools in a SINGLE message with ToolSearch calls:
37
+ - `ToolSearch("select:mcp__sellable__get_auth_status")`
38
+ - `ToolSearch("select:mcp__sellable__bootstrap_engage")`
39
+ - `ToolSearch("select:mcp__sellable__bootstrap_engage_multi")`
40
+ - `ToolSearch("select:mcp__sellable__get_engage_memory")`
41
+ - `ToolSearch("select:mcp__sellable__set_engage_style_guide")`
42
+ - `ToolSearch("select:mcp__sellable__record_engage_proven_search")`
43
+ - `ToolSearch("select:mcp__sellable__upsert_engage_tracked_person")`
44
+ - `ToolSearch("select:mcp__sellable__copy_sender_config")`
45
+ - `ToolSearch("select:mcp__sellable__migrate_flat_configs")`
46
+ - `ToolSearch("select:mcp__sellable__search_engagement_posts")`
47
+ - `ToolSearch("select:mcp__sellable__fetch_linkedin_posts")`
48
+ - `ToolSearch("select:mcp__sellable__add_to_comment_campaign")`
49
+ - `ToolSearch("select:mcp__sellable__start_direct_campaign")`
50
+ - `ToolSearch("select:mcp__sellable__pause_direct_campaign")`
51
+
52
+ Then proceed directly to Pre-Phase (Mode Detection). All auth, memory, and config loading steps are defined in Phase 0 — do NOT duplicate them here.
53
+ </bootstrap>
54
+
55
+ <tools>
56
+
57
+ ## MCP Tools
58
+
59
+ - `mcp__sellable__get_auth_status` - Verify token + workspace context
60
+ - `mcp__sellable__bootstrap_engage` - Single-sender resolve + ensure comment campaign table + fetch engaged post URLs; persists defaults
61
+ - `mcp__sellable__bootstrap_engage_multi` - Multi-sender resolve: parallel per-sender table creation + engaged post fetch + globalEngagedPostUrls union
62
+ - `mcp__sellable__get_engage_memory` - Read memory from `.sellable/configs/` (style guide, proven searches, tracked people). Accepts optional `senderId` for per-sender configs.
63
+ - `mcp__sellable__set_engage_style_guide` - Write style guide. Accepts optional `senderId` for per-sender configs.
64
+ - `mcp__sellable__record_engage_proven_search` - Update keyword stats. Accepts optional `senderId` for per-sender configs.
65
+ - `mcp__sellable__upsert_engage_tracked_person` - Add/update tracked person. Accepts optional `senderId` for per-sender configs.
66
+ - `mcp__sellable__copy_sender_config` - Copy all per-sender config files from one sender to another
67
+ - `mcp__sellable__migrate_flat_configs` - One-time migration of flat configs into senders/{senderId}/
68
+ - `mcp__sellable__search_engagement_posts` - Wide post discovery by keyword (no campaignOfferId required)
69
+ - `mcp__sellable__fetch_linkedin_posts` - Fetch recent posts for tracked people
70
+ - `mcp__sellable__add_to_comment_campaign` - Load approved comments into the comment campaign table
71
+ - `mcp__sellable__start_direct_campaign` - Start the comment campaign (optional)
72
+ - `mcp__sellable__pause_direct_campaign` - Pause the comment campaign (optional)
73
+
74
+ ## Built-in Tools
75
+
76
+ - Task - Parallel discovery agents (fresh-scanner + deep-scanner)
77
+ - AskUserQuestion - Optional interview + approvals
78
+ - Read - Load voice configs, post filters, and cross-skill insights from `.sellable/configs/` and `.sellable/insights/`
79
+ - Write - Save session insights to `.sellable/insights/`
80
+
81
+ </tools>
82
+
83
+ <process>
84
+
85
+ ## Pre-Phase: Mode Detection + Target Count [REQUIRED]
86
+
87
+ Detect mode and optional target count from the user's command:
88
+
89
+ | User says | Mode | Target |
90
+ | ----------------------------------------- | ------------------------- | ---------------- |
91
+ | `engage auto` / `engage autonomous` | **AUTONOMOUS** | default (10-15) |
92
+ | `engage` / `engage interactive` | **INTERACTIVE** (default) | default (10-15) |
93
+ | `engage for 3 comments` / `engage auto 5` | detected mode | **N** per sender |
94
+
95
+ **Target count parsing:** If the user includes a number (e.g., "engage for 3", "engage auto 5 comments", "engage 8"), use that as `targetPerSender` — the number of comments to draft **per sender**. This controls how many posts to assign to each sender in Phase 2 round-robin. Total posts shortlisted = `targetPerSender × number of senders`. Default is 5 per sender.
96
+
97
+ Store the mode and `targetComments` for use throughout the session. In **autonomous** mode:
98
+
99
+ - Skip Phase 3 (Interview) entirely
100
+ - Skip user approval in Phase 2 (shortlist) and Phase 4 (drafts)
101
+ - Auto-load in Phase 5 (no confirmation needed)
102
+ - Campaigns are always left **paused** (both modes)
103
+
104
+ ## Phase 0: Bootstrap All Senders + Keyword Strategy [REQUIRED]
105
+
106
+ ### Step 0.1: Auth check
107
+
108
+ Run `get_auth_status`. If not OK, stop and ask user to fix auth/workspace.
109
+
110
+ ### Step 0.2: Resolve senders
111
+
112
+ **AUTONOMOUS mode** or **multi-sender**:
113
+
114
+ - Call `bootstrap_engage_multi({ allSenders: true })`.
115
+ - This returns `senders[]` (each with `senderId`, `commentCampaignTableId`, `engagedPostUrls`, `hasConfig`) and `globalEngagedPostUrls`.
116
+
117
+ **INTERACTIVE mode with single sender** (backward compat):
118
+
119
+ - Call `bootstrap_engage()` to resolve sender.
120
+ - If `needsUserChoice: true`:
121
+ - `no_senders`: stop with instructions to add one at `https://app.sellable.dev/linkedin-accounts`.
122
+ - otherwise: ask user to choose sender, then call `bootstrap_engage({ senderId })`.
123
+ - Store `senderId`, `commentCampaignTableId`, and `engagedPostUrls`.
124
+ - For single-sender interactive, `globalEngagedPostUrls = engagedPostUrls`.
125
+
126
+ **INTERACTIVE mode with multiple senders**:
127
+
128
+ - Call `bootstrap_engage_multi({ allSenders: true })`.
129
+ - Present the sender list and let the user select which senders to include this session.
130
+ - If user picks a subset, proceed with only those senders.
131
+
132
+ ### Step 0.2.1: Per-sender config check
133
+
134
+ For EACH sender from `bootstrap_engage_multi`, check the `hasConfig` field:
135
+
136
+ **If sender has NO config (`hasConfig: false`):**
137
+
138
+ _Interactive mode:_
139
+
140
+ ```
141
+ Sender "[name]" has no engage config yet.
142
+
143
+ Options:
144
+ 1. Create fresh — I'll interview [name] to build their voice profile
145
+ 2. Copy from [first sender with config] — Start with their config, customize later
146
+ 3. Skip [name] this session — Only run engage for senders with configs
147
+ ```
148
+
149
+ _Autonomous mode:_
150
+
151
+ - If another sender has config: `copy_sender_config({ fromSenderId, toSenderId })` silently
152
+ - If NO sender has config: `migrate_flat_configs({ senderId })` for the first sender (moves flat configs into per-sender dir), then copy to others
153
+
154
+ **If `senders/` directory doesn't exist at all (first multi-sender run):**
155
+
156
+ - Call `migrate_flat_configs({ senderId })` for the first sender
157
+ - Copy to other senders as needed
158
+
159
+ ### Step 0.3: Per-sender voice calibration [REQUIRED]
160
+
161
+ For EACH sender, call `fetch_linkedin_posts({ linkedinUrl: sender.senderLinkedinProfileUrl, limit: 10 })`:
162
+
163
+ - Store the top 5 by engagement as voice reference samples for that sender
164
+ - Note the comment style, tone, and rhythm each sender actually uses
165
+ - These are used during drafting (Phase 4) so each sender's comments sound different
166
+
167
+ ### Step 0.4: Load per-sender memory [REQUIRED]
168
+
169
+ For EACH sender, call `get_engage_memory({ senderId })`:
170
+
171
+ - This reads from `senders/{senderId}/styleguide-core.md`, `senders/{senderId}/proven-searches.md`, `senders/{senderId}/influencers.md`
172
+ - Falls back to flat configs if sender dir doesn't exist
173
+
174
+ ### Step 0.5: Read shared writing configs [REQUIRED]
175
+
176
+ Read (built-in Read tool):
177
+
178
+ - `./.sellable/configs/writing/comments.md` (comment-specific rules, quality gate, approved examples)
179
+ - Per-sender `styleguide-core.md` is already loaded via `get_engage_memory` above
180
+
181
+ ### Step 0.6: Read cross-skill context [OPTIONAL]
182
+
183
+ Read (lightweight — local files only, no API calls):
184
+
185
+ - `./.sellable/configs/audience/icp.md` (for relevance scoring in Phase 2)
186
+ - `./.sellable/insights/cross-skill.md` (learnings from other skills)
187
+ - `./.sellable/insights/post-sessions.md` (**skim latest entry only** — trending topics)
188
+ - If any file doesn't exist, skip silently.
189
+
190
+ ### Step 0.7: Build keyword strategy [REQUIRED]
191
+
192
+ Build keywords from ALL senders' combined expertise:
193
+
194
+ - Extract expertise topics from each sender's style guide (Core Thesis, Key Beliefs)
195
+ - Cross-reference with proven searches from all senders — sort by hit rate, take top 5
196
+ - Check cross-skill insights for trending topics
197
+ - Add 3-5 exploratory keywords NOT already in proven searches
198
+ - Split into Tier 1 (fresh, core expertise) and Tier 2 (broader, proven high-hit-rate)
199
+
200
+ **Launch Phase 1 agents immediately after bootstrap.**
201
+
202
+ ## Phase 1: Smart Discovery (2 Parallel Agents) [REQUIRED — unchanged]
203
+
204
+ Two agents run in parallel, each optimized for a different time horizon. **Both use `globalEngagedPostUrls` for exclusion** — this is the union of ALL senders' previously engaged post URLs, preventing any post from being assigned to a sender who (or whose peer) already commented on it.
205
+
206
+ ### Agent: fresh-scanner (Task agent)
207
+
208
+ **Goal:** Find posts from the last 0-24 hours that are relevant to the senders' space.
209
+
210
+ **Process:**
211
+
212
+ 1. Call `search_engagement_posts` with Tier 1 keywords:
213
+ - `maxAgeDays: 1`
214
+ - `minTotalEngagement: 10`
215
+ - `maxPosts: 20`
216
+ - `excludePostUrls: globalEngagedPostUrls`
217
+ 2. Call `fetch_linkedin_posts` for tracked people from ALL senders' `memory.trackedPeople` (merged, deduped by URL).
218
+ 3. Filter through `post-filters.md` exclusion rules.
219
+ 4. For each post, compute `ageHours` from `postedAt`.
220
+ 5. Return all results with: `url`, `author`, `engagement`, `contentPreview`, `ageHours`, `matchedKeyword`.
221
+
222
+ **Input provided:**
223
+
224
+ - Tier 1 keywords
225
+ - Merged `trackedPeople` from all senders
226
+ - `globalEngagedPostUrls` for dedupe
227
+ - `post-filters.md` rules
228
+ - Combined sender expertise topics
229
+
230
+ ### Agent: deep-scanner (Task agent, parallel with fresh-scanner)
231
+
232
+ **Goal:** Find older (1-7 day) posts with proven high engagement.
233
+
234
+ **Process:**
235
+
236
+ 1. Call `search_engagement_posts` with Tier 2 keywords:
237
+ - `maxAgeDays: 7`
238
+ - `minTotalEngagement: 50`
239
+ - `maxPosts: 25`
240
+ - `excludePostUrls: globalEngagedPostUrls`
241
+ 2. Run a second search with Tier 1 keywords at:
242
+ - `maxAgeDays: 3`
243
+ - `minTotalEngagement: 30`
244
+ 3. Filter through `post-filters.md`.
245
+ 4. Return all results with same schema as fresh-scanner.
246
+
247
+ ### Quality Gate: Discovery
248
+
249
+ - [ ] Both agents returned results. If one returned 0, re-run with broader keywords.
250
+ - [ ] At least 15 total candidate posts. If fewer: retry with top 3 proven keywords, `maxAgeDays: 7`, `minTotalEngagement: 20`. Maximum 1 retry.
251
+ - [ ] At least 3 fresh (0-24h) posts found (ideal — not a hard fail).
252
+
253
+ ## Phase 2: Strategic Shortlist + Sender Assignment [REQUIRED]
254
+
255
+ ### Process
256
+
257
+ 1. **Merge** all results from both agents. Deduplicate by normalized URL.
258
+
259
+ 2. **Score each post** with weighted formula:
260
+
261
+ | Criterion | Weight | Scoring |
262
+ | -------------- | ------ | -------------------------------------------------------------------------------------------- |
263
+ | Recency | 40% | 0-6h = 10, 6-12h = 8, 12-24h = 6, 1-3d = 3, 3-7d = 1 |
264
+ | Relevance | 35% | 10 = directly about senders' core thesis. 7-8 = adjacent. 4-6 = industry. 1-3 = tangential. |
265
+ | Engagement | 15% | Normalized total engagement relative to pool |
266
+ | Commentability | 10% | 10 = debatable claim/question/framework. 5 = shares experience. 1 = announcement/self-promo. |
267
+
268
+ 3. **Select top N posts** where N = `targetPerSender × number of senders`. For example: 3 senders × 5 per sender = 15 posts shortlisted.
269
+
270
+ 4. **Post selection quality gate** — for EACH shortlisted post, it must pass ALL:
271
+
272
+ - [ ] Can a sender add genuine insight?
273
+ - [ ] Is there a specific claim to respond to?
274
+ - [ ] Is this the right audience? (check against ICP)
275
+ - [ ] Is commenting still valuable at this age?
276
+ - [ ] Not a trap post (engagement bait, politics, etc.)
277
+
278
+ 5. **Round-robin assign posts to senders** (fresh posts first, then older):
279
+
280
+ ```
281
+ Posts sorted by score descending. Senders in rotation order.
282
+ Post 1 → Sender A
283
+ Post 2 → Sender B
284
+ Post 3 → Sender C
285
+ Post 4 → Sender A
286
+ ...
287
+ Each post URL appears in exactly ONE sender's batch. Enforced structurally.
288
+ ```
289
+
290
+ When assigning, consider sender-post fit: if a post is particularly relevant to one sender's expertise, prefer assigning it to them even if it breaks strict rotation.
291
+
292
+ 6. For each post, write a 1-sentence "angle" note.
293
+
294
+ 7. Apply include/exclude signals from `post-filters.md` as a final pass.
295
+
296
+ 8. **Present the shortlist:**
297
+
298
+ **Interactive mode:**
299
+
300
+ ```
301
+ ## Found [N] posts for [M] senders
302
+
303
+ ### Fresh (< 24 hours) — highest visibility
304
+ | # | Age | Author | Preview | Engagement | Sender | Angle |
305
+ |---|-----|--------|---------|------------|--------|-------|
306
+ | 1 | 3h | [name] | [preview] | [N] | Chris | [angle] |
307
+ | 2 | 5h | [name] | [preview] | [N] | Thomas | [angle] |
308
+
309
+ ### Older (1-7 days) — high engagement
310
+ | # | Age | Author | Preview | Engagement | Sender | Angle |
311
+ |---|-----|--------|---------|------------|--------|-------|
312
+ | 6 | 2d | [name] | [preview] | [N] | Chris | [angle] |
313
+ ```
314
+
315
+ Ask: "Drop any rows you don't want, reassign senders, or say 'all' to keep everything."
316
+
317
+ **Autonomous mode:** Proceed silently with all posts. No user interaction.
318
+
319
+ ## Phase 3: Interview (Mine for Insights) [INTERACTIVE ONLY]
320
+
321
+ **Autonomous mode: SKIP entirely.**
322
+
323
+ **Interactive mode:** This phase always runs unless the user explicitly says "skip."
324
+
325
+ ### Mode: Light Interview (style guide exists for at least one sender)
326
+
327
+ Pick the 2-3 most interesting posts from the approved shortlist. Use `AskUserQuestion` for 2 rounds:
328
+
329
+ **Round 1 — Contrarian mining:**
330
+
331
+ > "[Author] says '[specific claim]'. What's the take most people will have — and where are they wrong?"
332
+
333
+ Push for specifics once. If still vague, accept and move on.
334
+
335
+ **Round 2 — Angle sharpening:**
336
+
337
+ > "For [Post A] and [Post B] — what would you actually say at a bar? Not the LinkedIn version."
338
+
339
+ **After both rounds:**
340
+
341
+ - Extract contrarian takes
342
+ - Map each take to specific posts AND the assigned sender
343
+ - Update relevant sender's style guide via `set_engage_style_guide({ markdown, senderId })`
344
+ - Reflect back extracted takes for confirmation
345
+
346
+ ### Mode: Full Interview (no style guide for any sender — required, cannot skip)
347
+
348
+ 3-4 rounds via `AskUserQuestion` (same as before — voice capture, heuristics, etc.).
349
+ Persist style guide for the primary sender, copy to others if appropriate.
350
+
351
+ ## Phase 4: Draft Comments Per Sender [REQUIRED]
352
+
353
+ Group posts by assigned sender. Process each sender's batch separately.
354
+
355
+ ### For Each Sender's Batch:
356
+
357
+ 1. **Load sender's voice profile** — their specific voice samples from Phase 0.3 + their per-sender style guide.
358
+
359
+ 2. **For each post** (internally, before showing):
360
+
361
+ - Pick the best angle (3 candidates → 1 winner, using angles from `comments.md`)
362
+ - If interview surfaced a contrarian take for this post, USE IT
363
+ - Draft using shared formatting rules from `comments.md` + sender-specific voice
364
+ - Self-edit once
365
+ - Quality gate (clarity, relevance, insight, coherence, cringe, substance)
366
+
367
+ 3. **Present batch:**
368
+
369
+ **Interactive mode:** Show as markdown table with sender name in header:
370
+
371
+ ```
372
+ ### Comments for [Sender Name] (5 posts)
373
+ | # | Age | Post (author + preview + link) | Comment | Angle |
374
+ ```
375
+
376
+ Wait for feedback per sender batch.
377
+
378
+ **Autonomous mode:** No presentation. Proceed to Phase 5.
379
+
380
+ ## Phase 5: Load Approved Comments Into Campaigns [REQUIRED]
381
+
382
+ ### Process
383
+
384
+ 1. **Summary:** "[N] comments for [M] senders — [X] for Chris, [Y] for Thomas, [Z] for Ike"
385
+
386
+ 2. **Interactive mode:** "Proceed?" — wait for explicit "yes".
387
+ **Autonomous mode:** Proceed automatically.
388
+
389
+ 3. For EACH sender, call:
390
+
391
+ ```
392
+ add_to_comment_campaign({ senderId, posts: [{ postUrl, comment }, ...] })
393
+ ```
394
+
395
+ One call per sender. Include ALL that sender's approved comments.
396
+
397
+ 4. **Leave campaigns PAUSED** (both modes). Do NOT auto-start.
398
+
399
+ 5. **Remind:** "Campaigns loaded but paused. Review in the dashboard, then start with `start_direct_campaign` when ready."
400
+
401
+ ## Phase 6: Save Session Insights [REQUIRED — always runs]
402
+
403
+ Everything we learned this session should help the NEXT session be better. **Per-sender memory is saved independently.**
404
+
405
+ ### 6A: Update Proven Searches (per sender)
406
+
407
+ For each keyword used in Phase 1, call `record_engage_proven_search({ keyword, totalReturned, postsYielded, senderId })` for EACH sender that received posts from that keyword.
408
+
409
+ ### 6B: Update Tracked People (per sender)
410
+
411
+ If any post authors from the shortlist are worth tracking, call `upsert_engage_tracked_person({ name, linkedinUrl, reason, senderId })` for the sender they were assigned to.
412
+
413
+ ### 6C: Save Session Insights to Style Guide (per sender)
414
+
415
+ For each sender that had comments drafted, update their style guide via `set_engage_style_guide({ markdown, senderId })`:
416
+
417
+ ```markdown
418
+ ## Engage Session — [date]
419
+
420
+ ### Comment Patterns That Worked
421
+
422
+ - [angles approved, voice preferences, verbatim approved examples]
423
+
424
+ ### Topics Getting Engagement This Week
425
+
426
+ - [Topic]: [avg engagement]
427
+
428
+ ### Contrarian Takes Mined (if interview happened)
429
+
430
+ - "[take 1]"
431
+
432
+ ### Keyword Performance This Session
433
+
434
+ - Fresh (0-24h): [keywords]
435
+ - Deep (1-7d): [keywords]
436
+ ```
437
+
438
+ ### 6D: Save Unused Post Angles (Top 9-10 Only)
439
+
440
+ Only keep the strongest unused angles for next session.
441
+
442
+ ### 6E: Update Cross-Skill Insights (shared)
443
+
444
+ **Append** to `.sellable/insights/engage-sessions.md`:
445
+
446
+ ```markdown
447
+ ## Session — [date]
448
+
449
+ **Stats**: [N] comments across [M] senders ([X] per sender avg). [N]% approval rate.
450
+
451
+ ### Sender Breakdown
452
+
453
+ - [Sender A]: [N] comments — [angles that worked]
454
+ - [Sender B]: [N] comments — [angles that worked]
455
+
456
+ ### Topics Getting Engagement
457
+
458
+ - [Topic 1]: [avg engagement] — [N] posts
459
+
460
+ ### Keyword Performance
461
+
462
+ - **Top fresh**: [keywords + hit rates]
463
+ - **Deprioritize**: [irrelevant keywords]
464
+ - **Try next**: [new keywords from trends]
465
+ ```
466
+
467
+ **If cross-skill insights found**, append to `.sellable/insights/cross-skill.md`:
468
+
469
+ - Format: `## From engage ([date])` with bullet points
470
+
471
+ ### Quality Gate: Session Saved
472
+
473
+ - [ ] Proven searches updated per sender for all keywords used
474
+ - [ ] New tracked people added per sender if discovered
475
+ - [ ] Comment patterns + approved examples saved to each sender's style guide
476
+ - [ ] Topic trends documented
477
+ - [ ] Contrarian takes persisted (if interview happened)
478
+ - [ ] `insights/engage-sessions.md` updated with multi-sender session summary
479
+ - [ ] `insights/cross-skill.md` updated if any cross-skill learnings found
480
+
481
+ </process>
482
+
483
+ <agent_team_orchestration>
484
+
485
+ ## Agent Architecture
486
+
487
+ ```
488
+ Lead Agent (you): Orchestrator + interviewer + drafter + approver + memory
489
+ |
490
+ |-- [PRE-PHASE — Mode detection]
491
+ |
492
+ |-- [PHASE 0 — Bootstrap all senders + per-sender voice + keyword strategy]
493
+ |
494
+ |-- [PHASE 1 — PARALLEL PAIR, launch immediately after Phase 0]
495
+ |
496
+ |-- Task Agent: fresh-scanner
497
+ | When: Phase 1 (parallel with deep-scanner)
498
+ | Job: Search 0-24h posts with Tier 1 keywords + tracked people.
499
+ | Low engagement threshold (10+). Fast.
500
+ | Tools: search_engagement_posts, fetch_linkedin_posts
501
+ | Input: Tier 1 keywords, merged trackedPeople, globalEngagedPostUrls,
502
+ | post-filters, combined sender expertise topics
503
+ | Output: Fresh posts (0-24h) with ageHours, engagement, preview
504
+ |
505
+ |-- Task Agent: deep-scanner
506
+ | When: Phase 1 (parallel with fresh-scanner)
507
+ | Job: Search 1-7 day posts with Tier 2 keywords (high threshold 50+)
508
+ | + catchup search with Tier 1 keywords at 1-3 days (threshold 30+).
509
+ | Tools: search_engagement_posts
510
+ | Input: Tier 2 + Tier 1 keywords, globalEngagedPostUrls,
511
+ | post-filters, ICP
512
+ | Output: Older high-engagement posts with same schema
513
+ |
514
+ |-- [PHASE 2 — Lead agent merges, scores, round-robin assigns to senders, presents]
515
+ |-- [PHASE 3 — Interview via AskUserQuestion (INTERACTIVE ONLY — skipped in autonomous)]
516
+ |-- [PHASE 4 — Lead agent drafts comments PER SENDER using each sender's voice]
517
+ |-- [PHASE 5 — Load per-sender campaigns (paused), remind to start]
518
+ |-- [PHASE 6 — Save per-sender memory + shared session insights]
519
+ ```
520
+
521
+ ### Parallelization Rules
522
+
523
+ - Phase 1: fresh-scanner + deep-scanner = PARALLEL (launch immediately)
524
+ - Phase 2: Shortlist + assignment = SEQUENTIAL on lead agent (needs both agents' results)
525
+ - Phase 3: Interview = SEQUENTIAL on lead agent (INTERACTIVE ONLY)
526
+ - Phase 4: Drafting = SEQUENTIAL on lead agent (per-sender batches)
527
+ - Phases 5-6: Load + Save = SEQUENTIAL on lead agent
528
+
529
+ </agent_team_orchestration>
530
+
531
+ <critical_rules>
532
+
533
+ ## Critical Rules
534
+
535
+ 1. **Never invent** facts, results, or personal experience. If unsure, write in a neutral, question-led style.
536
+ 2. **Do not load** any comments into the comment campaign without explicit user approval (interactive) or autonomous mode confirmation.
537
+ 3. **Always dedupe using `globalEngagedPostUrls`** — the UNION of all senders' engaged URLs. No post should appear in more than one sender's batch.
538
+ 4. **Fresh posts first** — 0-24h posts are highest value. Always present and draft these before older posts.
539
+ 5. **Avoid spammy engagement** — no empty praise, no emoji-laden fluff, no engagement bait.
540
+ 6. **Every comment must reply TO the post** — reference a specific claim, number, or framing. If it could work under any post, it's too generic.
541
+ 7. **Insight is non-negotiable** — the middle section must add a genuine new idea.
542
+ 8. **Interview always runs in interactive mode unless explicitly skipped** — use `AskUserQuestion` with targeted questions grounded in specific posts. **Skipped entirely in autonomous mode.**
543
+ 9. **Save session insights after every session** — Phase 6 runs regardless of mode. Per-sender memory (proven searches, tracked people, style guide) + shared insights must be persisted.
544
+ 10. **Each post URL → exactly ONE sender** — enforced by round-robin assignment. No post appears in multiple senders' campaign loads.
545
+ 11. **Per-sender voice** — each sender's comments are drafted using THEIR voice profile, not a shared one. Comments for Chris should sound like Chris, not like Thomas.
546
+ 12. **Campaigns always load PAUSED** — never auto-start in either mode. Remind user to review and start manually.
547
+ 13. **Don't over-engineer comments** — they're 2-4 sentences. Draft, self-edit once, quality gate.
548
+
549
+ </critical_rules>
@@ -0,0 +1,23 @@
1
+ # Engage Skill — Core
2
+
3
+ ## Where Data Lives
4
+
5
+ All engage memory lives in `.sellable/configs/` at the project root — the single source of truth for both user customization and MCP tool memory.
6
+
7
+ | Data | Config File | MCP Tool |
8
+ | --------------- | ------------------------------------------------ | ---------------------------------------------------- |
9
+ | Style guide | `.sellable/configs/writing/styleguide-core.md` | `get_engage_memory` / `set_engage_style_guide` |
10
+ | Comment rules | `.sellable/configs/writing/comments.md` | (read via `get_engage_memory`) |
11
+ | Proven searches | `.sellable/configs/discovery/proven-searches.md` | `get_engage_memory` / `record_engage_proven_search` |
12
+ | Tracked people | `.sellable/configs/discovery/influencers.md` | `get_engage_memory` / `upsert_engage_tracked_person` |
13
+ | Post filters | `.sellable/configs/discovery/post-filters.md` | (read by skill via Read tool) |
14
+ | ICP | `.sellable/configs/audience/icp.md` | (read by skill via Read tool) |
15
+
16
+ ## How Skills Update Configs
17
+
18
+ - **Interview skill**: Populates style guide, comments, ICP, and tracked people from a voice-first conversation
19
+ - **Engage skill**: Updates proven searches after each session, adds new tracked people when discovered
20
+
21
+ ## Migration from JSON
22
+
23
+ The old `proven-searches.json`, `tracked-people.json`, and `style-guide.template.md` files have been replaced. All data now lives as readable markdown in `.sellable/configs/`.
@@ -0,0 +1,11 @@
1
+ {
2
+ "searches": [],
3
+ "_schema": {
4
+ "keyword": "string - the search term used",
5
+ "lastUsed": "ISO date string - when this term was last searched",
6
+ "postsYielded": "number - how many posts were selected from results of this search",
7
+ "totalReturned": "number - how many posts were returned by search_signals",
8
+ "hitRate": "number - postsYielded / totalReturned (0-1)"
9
+ },
10
+ "_notes": "Updated automatically after each engagement session. High hitRate terms are prioritized in future searches."
11
+ }
@@ -0,0 +1,47 @@
1
+ # Commenting Style Guide
2
+
3
+ ## Voice & Tone
4
+
5
+ - **Philosophy:** [value-add / conversational / thought-leadership / mix]
6
+ - **Tone:** [professional / casual / witty / direct]
7
+ - **Length target:** [2-3 sentences / 3-5 sentences]
8
+
9
+ ## Topics I Have Strong Takes On
10
+
11
+ <!-- Topics where you can add genuine insight. List 3-5. -->
12
+
13
+ 1.
14
+ 2.
15
+ 3.
16
+
17
+ ## Hot Takes & Insights
18
+
19
+ <!-- Counterintuitive observations, frameworks, or data points you bring up often. -->
20
+
21
+ -
22
+
23
+ ## Example Comments (Good)
24
+
25
+ <!-- Paste 2-3 of your best LinkedIn comments that represent your voice. -->
26
+
27
+ ### Example 1
28
+
29
+ >
30
+
31
+ ### Example 2
32
+
33
+ >
34
+
35
+ ## Dos
36
+
37
+ -
38
+
39
+ ## Don'ts
40
+
41
+ -
42
+
43
+ ## Signature Phrases / Patterns
44
+
45
+ <!-- Optional: recurring structures or phrases you naturally use. -->
46
+
47
+ -
@@ -0,0 +1,10 @@
1
+ {
2
+ "people": [],
3
+ "_schema": {
4
+ "name": "string - display name",
5
+ "linkedinUrl": "string - full LinkedIn profile URL",
6
+ "reason": "string - why tracking this person (e.g. 'thought leader in B2B sales')",
7
+ "addedAt": "ISO date string"
8
+ },
9
+ "_notes": "User-managed list. The engage skill checks these profiles for recent posts during discovery."
10
+ }