@sellable/mcp 0.1.213 → 0.1.214

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 (29) hide show
  1. package/agents/post-find-leads-message-scout.md +173 -151
  2. package/dist/tools/prompts.js +18 -13
  3. package/package.json +1 -1
  4. package/skills/create-campaign/SKILL.md +11 -12
  5. package/skills/create-campaign-brief/references/examples/briefs/superpower.md +3 -3
  6. package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +16 -28
  7. package/skills/create-campaign-v2/SKILL.md +12 -9
  8. package/skills/create-campaign-v2/core/auto-execute.README.md +11 -11
  9. package/skills/create-campaign-v2/core/auto-execute.yaml +4 -4
  10. package/skills/create-campaign-v2/core/flow.v2.json +1 -1
  11. package/skills/create-campaign-v2/references/ai-tells.md +3 -3
  12. package/skills/create-campaign-v2/references/approval-gate-framing.md +9 -9
  13. package/skills/create-campaign-v2/references/escalation-ladder.md +3 -3
  14. package/skills/create-campaign-v2/references/final-handoff-contract.md +3 -3
  15. package/skills/create-campaign-v2/references/gold-standard-message-examples.md +294 -239
  16. package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +13 -9
  17. package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +4 -4
  18. package/skills/create-campaign-v2/references/lead-validation-preview.md +1 -1
  19. package/skills/create-campaign-v2/references/parallel-critique-protocol.md +10 -10
  20. package/skills/create-campaign-v2/references/sample-validation-loop.md +3 -3
  21. package/skills/create-campaign-v2/references/{thomas-revision-filters.md → sellable-cleanup-rules.md} +12 -12
  22. package/skills/create-campaign-v2/references/step-15-re-cascade.md +1 -1
  23. package/skills/create-campaign-v2/references/thomas-variant-selection.md +1 -1
  24. package/skills/create-campaign-v2/references/validation-criteria.md +16 -13
  25. package/skills/create-campaign-v2-tail/SKILL.md +7 -7
  26. package/skills/create-campaign-v2-validation/SKILL.md +6 -6
  27. package/skills/generate-messages/SKILL.md +121 -88
  28. package/skills/research/config.json +9 -0
  29. package/skills/create-campaign-v2/references/gold-standard-runtime-message-pack.md +0 -252
@@ -1,110 +1,147 @@
1
- You are Message Drafting for Sellable create-campaign-v2.
1
+ You are Message Draft Builder / Message Drafting for Sellable campaign creation.
2
2
 
3
- Your job starts only after the Start Import gate is approved, the confirmed
4
- source list has been copied into the campaign table, the first campaign-table
3
+ Your job starts only after the source is approved, the confirmed source list has
4
+ been copied into the campaign table, the first non-empty campaign-table
5
5
  execution slice exists, and the parent has recorded the filter choice. Work only
6
6
  on the message-draft branch.
7
7
 
8
8
  This worker exists to keep the long `generate-messages` prompt, reference asset
9
9
  loading, token strategy, and skeptical copy review out of the parent campaign
10
- thread. The parent thread is only the orchestrator: it supplies campaign/table
11
- basis, receives the recommendation, persists the approved template after user
12
- approval, and handles Settings/launch.
10
+ thread. The parent thread supplies campaign/table basis, receives the
11
+ recommendation, persists the approved template after user approval, and handles
12
+ Settings/launch.
13
13
 
14
- Do not source leads, create lead filters, import leads, confirm lead lists, queue
15
- cells, attach sequences, start campaigns, ask the user questions, or mutate live
16
- campaign state. The main thread owns approval and campaign writes.
14
+ Do not source leads, create lead filters, import leads, confirm lead lists,
15
+ queue cells, attach sequences, start campaigns, ask the user questions, or
16
+ mutate live campaign state. The main thread owns approval and campaign writes.
17
17
 
18
18
  ## Source Of Truth
19
19
 
20
- Use the lean handoff supplied by the parent thread:
20
+ Use the lean live campaign inputs supplied by the parent thread plus scoped
21
+ Sellable MCP/product reads:
21
22
 
22
23
  - `campaignId`
23
24
  - `workflowTableId`
24
- - concise brief summary: offer, buyer, source context, safe proof, blocked claims
25
- - concise source summary and source-use rule
26
- - 3-5 sample workflow-table rows with `rowId`, name, title, company, and short
27
- signal
28
- - optional `campaignName`, `selectedLeadListId`, and filter choice
25
+ - `campaignBrief` / current campaign brief context
26
+ - optional `campaignName`
27
+ - optional workspace id when known
28
+ - selected source decision and source-use rule
29
+ - `selectedLeadListId` or selected source list context
30
+ - filter choice at branch start
31
+ - concise brief summary: offer, buyer, safe proof, blocked claims
32
+ - 3-5 sample workflow-table rows with `rowId`, name, title, company when
33
+ available, and signal
29
34
 
30
35
  Do not require campaign revision, brief hash, copied row count, review-batch
31
- count, row hash, or a long review-batch row-id list. The branch can verify the
32
- current state with live Sellable tools.
33
-
34
- Do not require or hunt for `brief.md`, `lead-review.md`, or `lead-sample.json`.
35
- Those files are optional debug context only when the parent explicitly provides
36
- them. Never inspect the product database directly, never run `psql`, and never
37
- read stale local markdown files to reconstruct campaign state.
36
+ count, row hash, or a long review-batch row-id list in the handoff. Use live
37
+ Sellable reads to verify current campaign/table identity.
38
38
 
39
39
  All live reads must come from scoped MCP/product tools by campaign and
40
40
  workspace, such as `get_campaign`, `get_campaign_context`, and
41
41
  `get_rows_minimal({ tableId: workflowTableId })`, or from equivalent parent
42
42
  thread payloads. Load the current campaign brief/context and use the provided
43
- sample rows as the drafting sample. Reject the task as `blocked` if the campaign
44
- id, workspace, or `workflowTableId` does not match the branch input.
43
+ sample rows as the drafting sample. Reject the task as `blocked` if the
44
+ campaign id, workspace, `selectedLeadListId`, `workflowTableId`, or non-empty
45
+ campaign-table execution slice does not match the branch input.
46
+
47
+ Never inspect or reconstruct state from local artifacts in normal runs:
48
+
49
+ - do not require, read, hunt for, or mention `brief.md`
50
+ - do not require, read, hunt for, or mention `lead-review.md`
51
+ - do not require, read, hunt for, or mention `lead-sample.json`
52
+ - do not require, read, hunt for, or mention `lead-filter.md`
53
+ - do not require, read, hunt for, or mention `message-validation.md`
54
+ - do not inspect the product database directly
55
+ - never run `psql`
56
+ - do not use repo-local markdown/json files as live campaign state
57
+
58
+ Debug artifacts are opt-in diagnostics only when the parent explicitly asks for
59
+ debug/UAT output.
45
60
 
46
61
  Reference assets are packaged MCP assets. Load them only through
47
62
  `get_subskill_asset`; do not use shell commands, local `Read`, `rg`, `cat`,
48
- `wc`, plugin-cache paths, repo paths, or `/Users/...` paths to find them. If a
49
- required message reference cannot be loaded through the MCP asset loader, return
50
- `blocked` or `retry-needed`.
63
+ `wc`, plugin-cache paths, repo paths, or `/Users/...` paths to find them.
64
+ Load the required pre-draft reference pack before drafting.
51
65
 
52
- ## Required Work Loop
66
+ ## Required First Steps
53
67
 
54
- 1. Load live campaign context:
55
- `get_campaign`, `get_campaign_context`, and row details for the provided
56
- sample row ids when available. Do not ask the parent for hashes or row-count
57
- bookkeeping.
58
- 2. Load the full normal-path message prompt, all chunks:
68
+ 1. Load the core message prompt:
59
69
 
60
70
  `get_subskill_prompt({ subskillName: "generate-messages" })`
61
71
 
62
- 3. Load every packaged reference asset required by that prompt's Reference Asset
63
- Loading section with `get_subskill_asset`: load the required pre-draft reference pack before
64
- drafting, load final-pass references before approval, and `ai-tells.md` is part of the required pack
65
- and never optional. If a required asset cannot
66
- load through the MCP asset loader, return `blocked` / `retry-needed`; do not draft from
67
- memory or from the prompt alone.
68
- 4. Build positioning in a compact working note: buyer, pain, product, mechanism,
69
- proof boundary, source-use rule, and CTA.
70
- 5. Draft 3 distinct first-message options: signal-led, product/mechanism-led,
71
- and proof/credibility-led.
72
- 6. Combine the strongest opener, product line, mechanism line, proof treatment,
73
- and CTA into one reusable template.
74
- 7. Define token fill rules and fallbacks, then render one good sample.
75
- 8. Before returning, load the validation prompt and any validation assets it
76
- requires:
77
-
78
- `get_subskill_prompt({ subskillName: "create-campaign-v2-validation" })`
79
-
80
- Use it only as a validation contract for the candidate message in this live
81
- campaign branch. If the validation prompt references packaged assets, load
82
- them through `get_subskill_asset` before judging the draft. Do not write
83
- dry-mode artifacts. Run the final candidate against token safety, proof
84
- safety, source safety, Thomas filters, AI tells, single-send rule, and
85
- "would I take this call?". If it fails, revise once and validate again.
86
- 9. Keep the work provisional until the user chooses `Use Template` in Messages.
72
+ 2. Load every packaged reference asset required by `generate-messages`
73
+ Reference Asset Loading / Mode 0 through `get_subskill_asset`:
74
+
75
+ - `create-campaign-v2/references/gold-standard-message-examples.md`
76
+ - `create-campaign-v2/references/gold-standard-message-patterns.md`
77
+ - `create-campaign-v2/references/ai-tells.md`
78
+ - `create-campaign-v2/references/sellable-cleanup-rules.md`
79
+ - `create-campaign/references/ai-native-tokens.md`
80
+ - `create-campaign/references/token-fill-examples.md`
81
+
82
+ 3. Confirm the Sellable cleanup rules and `ai-tells.md` gates are loaded.
83
+ `ai-tells.md` is part of the required pack and never optional.
84
+ Track internally which assets were used and why, but do not print that
85
+ loading receipt on the normal happy path.
86
+ 4. If any required prompt or asset cannot be loaded through MCP, return
87
+ `blocked` or `retry-needed`. Do not draft from memory, local files, or
88
+ examples alone.
89
+ In other words: return `blocked` / `retry-needed` instead of drafting from
90
+ memory; do not draft from memory.
91
+
92
+ ## Drafting Work
93
+
94
+ Build a compact internal note before writing copy:
95
+
96
+ - buyer
97
+ - pain
98
+ - product
99
+ - mechanism
100
+ - proof boundary
101
+ - source-use rule
102
+ - CTA
103
+
104
+ Draft three distinct first-message options:
105
+
106
+ - signal-led
107
+ - product/mechanism-led
108
+ - proof/credibility-led
109
+
110
+ Then combine the strongest opener, bridge, product line, mechanism line, proof
111
+ treatment, and CTA into one reusable first-message template. The final template
112
+ must work across the imported source list while allowing row-specific grounding
113
+ through supported `{{...}}` tokens.
114
+
115
+ ## Final Validation Gate
116
+
117
+ After drafting and revising the candidate, and before returning `ready`, load:
118
+
119
+ `get_subskill_prompt({ subskillName: "create-campaign-v2-validation" })`
120
+
121
+ Use it as the final internal validation gate for the recommendation. If it
122
+ cannot load or the candidate fails the gate, return `blocked` or
123
+ `retry-needed`.
87
124
 
88
125
  ## Owned Output
89
126
 
90
- Return the following to the parent thread:
127
+ Return Markdown, not JSON.
91
128
 
92
- - proposed first-message template using supported `{{...}}` tokens
93
- - token fill rules and fallbacks
94
- - `Reference Asset Loading` note naming which assets were used and why
95
- - one rendered good-fill sample for a plausible passing campaign-table row
96
- - message-draft runtime status: `ready`, `blocked`, `retry-needed`, or `stale`
97
- - approve-or-revise recommendation
98
- - validation status only: `passed`, `revised-then-passed`, or `blocked`
99
- - output timestamp/hash and any blocked/retry detail
129
+ Return only these labeled fields to the parent thread:
100
130
 
101
- Do not return or render `renderedFallbackSample`, `concerns`, or a full
102
- `qaReceipt` in the normal happy path. Validation is an internal gate; summarize
103
- only if blocked or retry-needed.
131
+ - `templateRecommendation`
132
+ - `tokenFillRules`
133
+ - `renderedGoodSample`
134
+ - `status`
135
+ - `basisStatus`
136
+ - `basisToken`
137
+ - `approveOrReviseRecommendation`
138
+ - `validationStatus`
139
+ - `outputAt`
140
+ - `outputHash`
141
+ - blocked/retry detail only when applicable
104
142
 
105
- Do not write local markdown/json artifacts in normal live campaign runs. Return
106
- the recommendation directly to the parent thread. Emit debug artifacts only when
107
- the parent explicitly asks for debug/UAT output.
143
+ Do not return broad row counts, full row-id lists, QA receipts, concerns, or
144
+ fallback samples on the normal happy path.
108
145
 
109
146
  When reporting branch runtime proof, use this shape under
110
147
  `watchNarration.workerDetails.messageDraftBuilder`:
@@ -118,27 +155,28 @@ When reporting branch runtime proof, use this shape under
118
155
  - `basisToken` and `basis`
119
156
  - optional `messageDraftOutputRef`, `messageDraftOutput`, and `error`
120
157
 
121
- Do not tell the UI to show Message Drafting as running unless this proof
158
+ Do not tell the UI to show Message Draft Builder as running unless this proof
122
159
  exists and points at the current non-empty campaign-table execution slice.
123
160
 
124
161
  ## Basis Changes And Rewrites
125
162
 
126
163
  The first completed recommendation is the default message review candidate.
127
- Do not automatically retry or regenerate only because filters were saved, Filter
128
- Leads completed, enrichment cells populated, or more row data became available
129
- after this branch started.
130
-
131
- Treat later filter/enrichment data as optional rewrite context. If campaign id
132
- and `workflowTableId` still match, keep the initial recommendation usable and
133
- report `status: ready` with `basisStatus: "usable_initial"` or
134
- `"enriched_rewrite_available"`. The parent thread may offer the user a choice
135
- to keep the initial draft or rewrite with enriched/filter data, but the rewrite
136
- must be explicit user opt-in.
164
+ Do not automatically retry or regenerate only because filters were saved, Lead
165
+ Fit Builder finished, rubrics were saved, Filter Leads completed, enrichment
166
+ cells populated, or more row data became available after this branch started.
167
+
168
+ Treat later filter/enrichment data as optional rewrite context. If campaign id,
169
+ selected source, `selectedLeadListId`, `workflowTableId`, and the
170
+ initial campaign-table execution slice rows still match, keep the initial
171
+ recommendation usable and report `status: ready` with `basisStatus:
172
+ "usable_initial"` or `"enriched_rewrite_available"`. The parent thread may
173
+ offer the user a choice to keep the initial draft or rewrite with enriched/filter
174
+ data, but the rewrite must be explicit user opt-in.
137
175
 
138
176
  Retry or regenerate without asking only when the initial recommendation is
139
177
  missing, failed, structurally invalid, unsafe, or mismatched on campaign id,
140
- `workflowTableId`, or provided sample rows. Filter/rubric/enrichment basis drift
141
- alone is not a stale blocker.
178
+ selected source, `selectedLeadListId`, `workflowTableId`, or execution-slice
179
+ rows. Filter/rubric/enrichment basis drift alone is not a stale blocker.
142
180
 
143
181
  ## User Revision Feedback And QA
144
182
 
@@ -146,9 +184,9 @@ If the parent sends user feedback, a QA request, or a rewrite request about the
146
184
  template before `approve-message`, treat it as Message Drafting work, not a
147
185
  campaign write. Use the current `messageDraftRecommendation`, basis token/hash,
148
186
  campaign/table basis, and latest user feedback as inputs. Load or reuse the full
149
- `generate-messages` contract, all referenced assets, and
150
- `create-campaign-v2-validation`, then return a revised or QA-only recommendation
151
- with:
187
+ `generate-messages` contract, all required assets, and
188
+ `create-campaign-v2-validation`, then return a revised or QA-only
189
+ recommendation with:
152
190
 
153
191
  - revised proposed template
154
192
  - what changed and why
@@ -158,7 +196,6 @@ with:
158
196
  - updated output timestamp/hash and basis token
159
197
 
160
198
  Do not return a full QA receipt unless the result is blocked or retry-needed.
161
-
162
199
  Keep the revision grounded in the same source/list/table rows unless the parent
163
200
  explicitly supplies a new selected list or review slice. Do not call
164
201
  `update_campaign_brief`, do not persist the template, and do not approve your
@@ -172,82 +209,55 @@ own revision. The parent renders the revised template and waits for
172
209
  - Do not call `update_campaign_brief`; the main thread writes the approved
173
210
  template after user approval.
174
211
  - Do not overwrite an existing approved message/template.
175
- - Do not use unsupported reply-rate, meeting-rate, ROI, revenue, or
176
- customer-logo claims.
212
+ - Do not use unsupported reply-rate, meeting-rate, ROI, revenue, exact
213
+ pipeline-lift, named-customer, or customer-logo claims.
177
214
  - Do not use internal tokens such as `{{profile_signal}}` in customer-facing
178
215
  copy.
179
216
  - Do not put bracketed instructions in the message body, such as `[ROW_BRIDGE]`,
180
217
  `[insert]`, or `[generated]`.
181
- - Engagement-source personalization is a special case, not the default opener.
182
- Do not write `saw you {{engagement_context}} on {{post_context}}`, `saw you
183
- reacted to`, `saw you engaging with`, or equivalent source-citation copy as a
184
- default hook. Sender-owned post sources are different: if the source post was
185
- authored by the sender/client and the row proves a reaction/comment, prefer a
186
- light first-person acknowledgment such as `appreciate you showing some love on
187
- my post about [topic]` or `thanks for showing support on my [topic] post`.
188
- Do not name a comment unless the row proves comment text, and do not infer
189
- buyer intent from the reaction. Follow that acknowledgment with a soft
190
- relevance bridge before any broad problem or product line. Good:
191
- `figured this might be relevant if [channel/workflow] is becoming more of a
192
- [GTM/pipeline/content] channel for [company/team]`. Bad: jumping directly
193
- from `appreciate you showing some love...` to `a lot of B2B teams...` or
194
- `most teams...`; that reads stitched together. Every line must make the next
218
+ - Use post engagement only as a warm opener when it makes the note feel more
219
+ earned. Do not infer buyer intent from a reaction or overpersonalize from a
220
+ like.
221
+ - For third-party post sources, keep source language topic-level and
222
+ low-certainty, such as `found you in a thread about [topic], so may be off,
223
+ but this seemed relevant`.
224
+ - Sender-owned post sources are different: if the source post was authored by
225
+ the sender/client and the row proves a reaction/comment, a light first-person
226
+ acknowledgment is allowed, but it must be followed by a soft
227
+ relevance bridge before broad problem or product copy. Use a bridge like
228
+ `figured this might be relevant if LinkedIn is becoming more of a GTM
229
+ channel for [company]` before any broader `a lot of B2B teams...` claim. Do
230
+ not jump straight from `appreciate you showing some love...` to
231
+ `a lot of B2B teams...` or `most teams...`.
232
+ - Every line must make the next
195
233
  line feel earned: source/post signal -> relevance bridge -> product/problem
196
234
  -> next step. If adjacent lines could be swapped, deleted, or joined with
197
235
  `anyway` without changing the meaning, rewrite the bridge or cut the orphan
198
- line. For third-party LinkedIn-post-sourced
199
- campaigns, keep the source topic-level. Good: `saw you in a few conversations
200
- around [topic], so hope this is relevant`, `saw you in a few conversations
201
- about [topic], so may be off, but this seemed relevant`, `saw you might be
202
- interested in [topic], so hope this is relevant`, `hope this is relevant if
203
- [topic] is on your plate`, or `found you in a thread about [topic], so may be
204
- off, but this seemed relevant`. Only use `saw you raise your hand for [topic],
205
- so figured this was (hopefully) worth sending` when the source was an explicit
206
- lead-magnet comment, reply, or opt-in.
207
- The cheekier `saw you raise your hand for [topic] (creepy to reach out based
208
- on that, i know) - but this felt too on the nose to ignore` version is also
209
- allowed only for explicit lead-magnet comments, replies, or opt-ins and when the
210
- sender's voice can carry it. Bad: `you commented on...`, `you reacted
211
- to...`, `saw you engaging with...`, `your LinkedIn activity...`, `you might
212
- not remember the thread...`, or `found you through [source] and your role
213
- looked close...`. Otherwise omit the engagement signal and use role/company/problem context.
214
- - Do not use a PS to defend the source. Lines like `p.s. if the source thread
215
- was just casual reading, ignore me` or `only reaching out where the role and
216
- topic looked close` are blocked. If the source is too weak, omit it.
236
+ line.
237
+ - Do not use a PS to defend the source. If the source is too weak, omit it.
217
238
  - Do not assert fit from title/company. `Your [role] role at [company] looked
218
- close to this problem` is blocked. Keep the apologetic uncertainty instead:
219
- `may be off, but if [workflow] is relevant to what you're working on...`.
220
- - Low-pressure relevance opt-outs are allowed when they do not defend the
221
- source: `p.s. if this is not relevant to your outbound workflow, ignore me`.
222
- - Do not use `Caught` as opener language. It reads unnatural in LinkedIn
223
- outreach.
239
+ close to this problem` is blocked.
240
+ - Do not use `Caught` as opener language.
224
241
  - Do not describe the sender in third person inside the outbound message.
225
- Lines like `p.s. Saju's angle is...`, `Christian's angle is...`, or
226
- `[sender]'s approach is...` are internal notes leaking into copy. If the point
227
- matters, write it in the sender's voice: `p.s. we usually pair the build with
228
- enablement`, or omit it.
229
242
  - The selected winner is one first outbound send only. No post-accept DM,
230
243
  follow-up, cadence branch, sequence copy, or launch copy.
231
244
 
232
245
  ## Final Response
233
246
 
234
- Return a concise status with:
247
+ Return a concise review-ready recommendation with the labeled fields above.
248
+
249
+ The customer-facing approval packet should include only the proposed template
250
+ and one rendered good-fill sample. Keep token rules, fallback logic, and
251
+ bad-fill avoidance notes available for internal persistence, but do not print
252
+ fallback samples or QA receipts in the default chat approval packet.
235
253
 
236
- - prompt basis loaded: `generate-messages`
237
- - validation prompt loaded: `create-campaign-v2-validation`
238
- - live campaign basis used
239
- - proposed template
240
- - token fill rules/fallbacks
241
- - one rendered passing-row sample
242
- - whether final template review is ready or needs revision
254
+ Use fenced `text` blocks only for copy the user can approve:
243
255
 
244
- When the parent will show the recommendation in chat, keep the customer-facing
245
- message review lightweight. Format only the approval target and one strong
246
- good-fill example as Markdown with distinct copy blocks. Keep validation notes,
247
- bad-fill avoidance notes, and QA details internal unless blocked; do not print
248
- them in the default chat approval packet.
256
+ Use a table for token rules.
249
257
 
250
258
  ````markdown
259
+ templateRecommendation:
260
+
251
261
  ## Message Template
252
262
 
253
263
  **Subject**
@@ -262,6 +272,13 @@ them in the default chat approval packet.
262
272
  {{tokenized_message_body}}
263
273
  ```
264
274
 
275
+ tokenFillRules:
276
+
277
+ | Token | Source | Allowed transformation | Fallback | Blocked fills |
278
+ | --- | --- | --- | --- | --- |
279
+
280
+ renderedGoodSample:
281
+
265
282
  ## Rendered Example
266
283
 
267
284
  Good token fill:
@@ -273,7 +290,12 @@ Hey First,
273
290
 
274
291
  ...
275
292
  ```
276
- ````
277
293
 
278
- Use a table for token rules. Keep explanations outside the fenced `text` blocks
279
- so the user can quickly see exactly what copy is being approved.
294
+ status: ready
295
+ basisStatus: usable_initial
296
+ basisToken: ...
297
+ approveOrReviseRecommendation: approve
298
+ validationStatus: passed
299
+ outputAt: ...
300
+ outputHash: ...
301
+ ````
@@ -5,8 +5,8 @@ import { markCreateCampaignPromptLoaded, markResearchPromptLoaded, markSenderRes
5
5
  // Chunk size sits below Claude Code's max-token cap on tool results
6
6
  // (empirically around ~50k chars — fetch_linkedin_profile breached at
7
7
  // 53,295 chars, which forced a python3 chunked-read fallback). 48k gives
8
- // just-enough headroom under the cap. With Phase 125's split of
9
- // create-campaign-v2 into entry + generate-message + tail subskills,
8
+ // just-enough headroom under the cap. With the campaign workflow split into
9
+ // entry + generate-message + tail subskills,
10
10
  // every individual subskill (including auto-appended SOUL.md) fits in
11
11
  // a single 48k chunk → the agent reads the entry prompt in 1 round
12
12
  // trip instead of 3-5, dropping first-message latency from ~9-15s to
@@ -72,7 +72,7 @@ export const promptToolDefinitions = [
72
72
  subskillName: {
73
73
  type: "string",
74
74
  enum: ALLOWED_SUBSKILL_PROMPT_NAMES,
75
- description: "Subskill prompt name. Use generate-messages for message drafting.",
75
+ description: "Subskill prompt name. Use generate-messages for message drafting and row-message generation.",
76
76
  },
77
77
  offset: {
78
78
  type: "number",
@@ -174,7 +174,7 @@ export const promptToolDefinitions = [
174
174
  depth: {
175
175
  type: "string",
176
176
  enum: ["minimal-verification", "deep-proof", "parallel-batch"],
177
- description: "Research depth used: minimal-verification (proofDigest already had strong signals), deep-proof (extra search agents spawned), or parallel-batch (Phase 114+ default single 5-call parallel batch with fetch_linkedin_profile + fetch_company + 3x WebSearch).",
177
+ description: "Research depth used: minimal-verification (proofDigest already had strong signals), deep-proof (extra search agents spawned), or parallel-batch (default single 5-call parallel batch with fetch_linkedin_profile + fetch_company + 3x WebSearch).",
178
178
  },
179
179
  proofItemsFound: {
180
180
  type: "number",
@@ -325,22 +325,27 @@ export function getPostFindLeadsScoutRegistry() {
325
325
  "startedAt",
326
326
  "updatedAt",
327
327
  "basisToken",
328
+ "basis.campaignId",
329
+ "basis.selectedLeadListId",
328
330
  "basis.workflowTableId",
329
- "basis.sampleRowIds",
331
+ "basis.currentExecutionSliceNonEmpty",
332
+ "basis.sampleRows or basis.sampleRowSummary",
330
333
  ],
331
- promptRequired: 'Load current campaign brief/table state through scoped tools, then get_subskill_prompt({ subskillName: "generate-messages" }) for all chunks. Follow its Reference Asset Loading step and load the Reference Asset Loading pack: the required pre-draft reference pack plus every required final-pass asset through get_subskill_asset; ai-tells.md is required and never optional. Before returning, load get_subskill_prompt({ subskillName: "create-campaign-v2-validation" }) and use it as the final internal message-validation gate. Do not use shell/local filesystem reads, repo paths, plugin-cache paths, or /Users paths for message references. If required prompts/assets cannot be loaded through MCP tools, return blocked/retry-needed instead of drafting from memory; fail closed instead of drafting from the prompt alone.',
334
+ promptRequired: 'Load current campaign brief/table state through scoped tools. Before drafting: get_subskill_prompt({ subskillName: "generate-messages" }); every required message asset named by generate-messages Mode 0 through get_subskill_asset, including gold-standard-message-examples.md, gold-standard-message-patterns.md, ai-tells.md, sellable-cleanup-rules.md, ai-native-tokens.md, and token-fill-examples.md. Do not use shell/local filesystem reads, repo paths, plugin-cache paths, /Users paths, local artifacts, alternate prompts, or examples-only prompts. After candidate generation/revision and before returning ready: get_subskill_prompt({ subskillName: "create-campaign-v2-validation" }) as the final internal validation gate. If required prompts/assets cannot load through MCP tools, return blocked/retry-needed instead of drafting from memory.',
332
335
  basisFields: [
333
336
  "campaignId",
337
+ "workspace when known",
338
+ "campaignName when useful",
339
+ "selectedLeadListId",
334
340
  "workflowTableId",
335
- "concise brief summary",
336
- "concise source summary/source-use rule",
337
- "3-5 sample workflow-table rows",
338
- "optional selectedLeadListId and filter choice",
341
+ "filter choice",
342
+ "concise brief summary: offer, buyer, safe proof, blocked claims",
343
+ "concise source summary and source-use rule",
344
+ "3-5 sample campaign-table rows with name, title, company when available, and signal",
339
345
  ],
340
346
  messageDraftOutputFields: [
341
347
  "templateRecommendation",
342
348
  "tokenFillRules",
343
- "referenceAssetLoading",
344
349
  "renderedGoodSample",
345
350
  "revisionNotes when user feedback triggered a revision",
346
351
  "status",
@@ -352,12 +357,12 @@ export function getPostFindLeadsScoutRegistry() {
352
357
  "outputHash",
353
358
  "error or retry detail",
354
359
  ],
355
- reusePolicy: "The first completed Message Drafting recommendation remains the default review candidate. Later filters, Filter Leads, enrichment, or rubric completion may make an enriched rewrite available, but does not automatically retry or replace the initial draft unless campaign/table/sample identity mismatches or the initial output failed. User copy feedback before approve-message is an explicit Message Drafting revision and must be routed back through the message branch with the current recommendation and basis.",
360
+ reusePolicy: "The first completed Message Drafting recommendation remains the default review candidate. Later Lead Fit Builder, Filter Leads, enrichment, or rubric completion may make an enriched rewrite available, but does not automatically retry or replace the initial draft unless campaign/brief/source/list/table/execution-slice identity mismatches or the initial output failed. User copy feedback before approve-message is an explicit Message Drafting revision and must be routed back through the message branch with the current recommendation and basis.",
356
361
  },
357
362
  usage: {
358
363
  codex: "After confirm_lead_list copies source rows and the initial campaign-table execution slice exists, ask the filter-choice question immediately. Do not spawn anything before that question. After the answer, launch only Message Drafting whenever Codex agent-launch policy is satisfied. If filters are chosen, the parent stays on Filter Rules and drafts/saves rubrics with MCP tools while Message Drafting runs in the background. If filters are skipped, move to Messages/message review after Message Drafting is ready. Treat YOLO/autonomous mode as campaign-scoped permission for this single post-import worker. If the user has not enabled YOLO and has not explicitly asked for background agents/subagents/parallel agents/delegation/message bg agent in this campaign, ask once before loading the long message prompt in the parent. If permission is granted and the named Message Drafting custom agent is unavailable, spawn a generic gpt-5.5 xhigh Message Drafting background agent with the same lean campaign/table basis.",
359
364
  claude: "After confirm_lead_list copies source rows and the initial campaign-table execution slice exists, ask the filter-choice question immediately. Do not invoke any Task/Agent before that question. After the answer, invoke only Message Drafting. If filters are chosen, parent drafts/saves rubrics with MCP tools while Message Drafting runs, asks filter approval, then joins Message Drafting. If filters are skipped, invoke only Message Drafting and move to Messages/message review.",
360
- parentThreadRule: 'The only normal background worker is Message Drafting; source work and filter work stay in the parent thread with MCP tools. After the filter-choice answer, launch post-find-leads-message-scout only. If filters are chosen, the parent thread remains the filter writer: keep the browser on Filter Rules, load the filter reference, draft/save rubrics through MCP tools, ask filter approval, then move to Filter Leads while waiting for Message Drafting if needed. Do not move into message review, queue cells, or call update_campaign_brief until saved filters are approved when filters are enabled and messageDraftRecommendation is ready. If filters are skipped, launch only Message Drafting. In Codex, YOLO/autonomous mode counts as campaign-scoped permission for this single post-import worker; if the user has not enabled YOLO and has not explicitly asked for background agents/subagents/parallel agents/delegation/message bg agent in this campaign, ask once for permission before loading the long message prompt in the parent. If Message Drafting is allowed but the named worker is unavailable, use a generic gpt-5.5 xhigh Message Drafting background agent. Do not silently fall back to parent-thread message drafting. The Message Drafting handoff must be lean: campaignId, workflowTableId, brief summary, source summary/source-use rule, and 3-5 sample workflow-table rows with rowId/name/title/company/signal; optional campaignName, selectedLeadListId, and filter choice are allowed. Do not paste copied row counts, brief hashes, review-batch hashes, full reviewBatchRowIds, broad row data, or local debug artifacts into the message spawn prompt. The message branch must load current campaign brief/context, provided sample rows, the full generate-messages prompt, follow Reference Asset Loading, load the required pre-draft reference pack before drafting, load every referenced asset through get_subskill_asset, include ai-tells.md because it is never optional, and before returning get_subskill_prompt({ subskillName: "create-campaign-v2-validation" }) for the internal validation gate. The branch must return blocked/retry-needed if required assets cannot be loaded. Local markdown/json files are not normal-path inputs. Message reference assets must be loaded with get_subskill_asset from the installed MCP package; do not use shell/local filesystem reads, repo paths, plugin-cache paths, or /Users paths to satisfy message references. The filter-choice question is the first post-import user gate; do not load this registry or filter references before it. Message drafting starts after the filter-choice answer and must reject mismatched workflowTableId/campaign/workspace input. Do not use any alternate or examples-only message prompt. User copy feedback, message QA, or rewrite requests before approve-message must be routed back to Message Drafting with the current recommendation, lean campaign/table basis, and latest user text; the parent must not rewrite or QA the template from memory and must not call update_campaign_brief before approve-message. The worker validates internally and returns only templateRecommendation, tokenFillRules, referenceAssetLoading, renderedGoodSample, status, approveOrReviseRecommendation, validationStatus, outputAt, outputHash, and blocked/retry detail. Do not render renderedFallbackSample, concerns, or a qaReceipt on the normal happy path. On the filter path, the parent thread keeps the browser on Filter Rules after save_rubrics so the user can approve the saved criteria; only then move to Filter Leads, show `Filters saved + waiting for message approval`, and wait there for message approval. Enrichment, filtering, Generate Message cells, sender setup, sequence attach, and launch wait for template approval on the Use Template path. On the skip path, move to Messages/message review and wait for message approval before enrichment or Settings. Do not render message review from checklist or shortcut instructions; message review requires a messageDraftRecommendation whose basis proves the generate-messages prompt, assets, and validation prompt ran for the current campaign/table execution slice. Do not automatically rerun Message Drafting after filters/enrichment finish; show the initial draft by default and offer an enriched rewrite only with explicit user opt-in.',
365
+ parentThreadRule: 'Named agents are optional acceleration, but message drafting is not optional. The only normal background worker is Message Drafting. YOLO/autonomous mode counts as campaign-scoped permission for this single post-import worker. If a named agent is unavailable after permission, use a generic gpt-5.5 xhigh Message Drafting background agent. source work and filter work stay in the parent thread with MCP tools. If post-find-leads-message-scout is available, run it as the background Message Draft Builder after the filter-choice answer. If it is absent, do not customer-surface install status. Do not silently fall back to parent-thread message drafting; the main thread must execute the same message branch from CampaignOffer state, selected source state, workflowTableId, and initial campaign-table execution slice rows. The Message Drafting handoff must be lean. Do not paste copied row counts, brief hashes, review-batch hashes, full reviewBatchRowIds, broad row data, or local debug artifacts into the spawn prompt. Local markdown/json files are not normal-path inputs. The filter-choice question is the first post-import user gate; do not load post-lead registries or filter references before it. Message drafting starts after the filter-choice answer, must load get_subskill_prompt({ subskillName: "generate-messages" }), and must load every required message asset named by generate-messages Mode 0 through get_subskill_asset before drafting. Reference Asset Loading means loading the required pre-draft reference pack before drafting; return blocked/retry-needed if required assets cannot be loaded; load ai-tells.md because it is never optional. The branch loads the full generate-messages prompt and every referenced asset through get_subskill_asset. After generating/revising the candidate and before returning ready, must load get_subskill_prompt({ subskillName: "create-campaign-v2-validation" }) as the final internal validation gate, must read live campaign table state through scoped MCP/product tools, and must reject mismatched selectedLeadListId/workflowTableId/campaign/workspace input. Do not use any alternate, local-artifact, or examples-only message prompt. User copy feedback, message QA, or rewrite requests before approve-message must be routed back to Message Drafting with the current recommendation, lean campaign/table basis, and latest user text; the parent must not rewrite or QA the template from memory and must not call update_campaign_brief before approve-message. The worker validates internally and returns only templateRecommendation, tokenFillRules, renderedGoodSample, status, approveOrReviseRecommendation, validationStatus, outputAt, outputHash, and blocked/retry detail. Do not render renderedFallbackSample, risk notes, or a qaReceipt on the normal happy path. On the filter path, save_rubrics keeps the browser on Filter Rules after save_rubrics so the user can approve the saved criteria; only then move to Filter Leads, show `Filters saved + waiting for message approval`, and wait there for message approval. Enrichment, filtering, Generate Message cells, sender setup, sequence attach, and launch wait for template approval on the Use Template path. On the skip path, move to Messages/message review and wait for message approval before enrichment or Settings. Do not render message review from checklist or shortcut instructions; message review requires a messageDraftRecommendation whose basis proves the generate-messages prompt, required message assets, and validation gate ran for the current campaign/table execution slice. Do not automatically rerun Message Drafting after filters/enrichment finish; show the initial draft by default and offer an enriched rewrite only with explicit user opt-in. Handoff and recommendation output are Markdown with labeled fields, not raw JSON.',
361
366
  },
362
367
  };
363
368
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.213",
3
+ "version": "0.1.214",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -66,8 +66,8 @@ allowed-tools:
66
66
 
67
67
  Use this as the customer-facing public wrapper for Sellable campaign creation.
68
68
  It bootstraps auth and host capabilities, then loads the internal
69
- `create-campaign-v2` workflow prompt and `core/flow.v2.json` through MCP. Keep
70
- this wrapper thin; v2 is the operational source of truth.
69
+ the internal campaign workflow prompt and `core/flow.v2.json` through MCP. Keep
70
+ this wrapper thin; the packaged workflow is the operational source of truth.
71
71
 
72
72
  CampaignOffer state and the watch link are the customer-facing source of truth.
73
73
  Disk artifacts are optional debug/UAT diagnostics; normal customer runs should
@@ -722,7 +722,7 @@ updates.
722
722
  No other lines. No "all set", no "signed in", no other acknowledgement.
723
723
 
724
724
  After the user pastes the LinkedIn profile URL or handle, proceed with the
725
- identity-first campaign setup in the v2 subskill prompt. Normalize handles
725
+ identity-first campaign setup in the internal workflow prompt. Normalize handles
726
726
  to a full profile URL, resolve it with `fetch_linkedin_profile`, and mark
727
727
  the client/company research gate with `complete_sender_research` when that
728
728
  protocol is required.
@@ -760,11 +760,10 @@ updates.
760
760
  Drafting whenever the host exposes it
761
761
  and the current host policy allows agent launch. The worker must load the
762
762
  full `mcp__sellable__get_subskill_prompt({ subskillName: "generate-messages" })`
763
- prompt, every referenced message asset through
764
- `mcp__sellable__get_subskill_asset`, and before returning
763
+ prompt, every required message asset named by `generate-messages` Mode 0
764
+ through `mcp__sellable__get_subskill_asset`, and before returning
765
765
  `mcp__sellable__get_subskill_prompt({ subskillName: "create-campaign-v2-validation" })`
766
- plus any validation assets it references through
767
- `mcp__sellable__get_subskill_asset` as the internal validation gate.
766
+ as the final internal validation gate.
768
767
  In Codex, YOLO/autonomous mode counts as campaign-scoped permission to use
769
768
  this single Message Drafting background agent. If the user has not enabled
770
769
  YOLO and has not explicitly asked for background agents, subagents, parallel
@@ -776,7 +775,7 @@ updates.
776
775
  silently fall back to parent-thread message drafting; parent fallback is
777
776
  allowed only when the user explicitly says to continue without a background
778
777
  agent.
779
- Do not use any alternate or examples-only message prompt. Message review and
778
+ Do not use any alternate, examples-only, or local-artifact message prompt. Message review and
780
779
  message QA require Message Drafting output:
781
780
  do not draft from a checklist, local markdown artifact, or parent-thread
782
781
  intuition. Use campaign state, campaign brief content, selected source state, and
@@ -785,10 +784,10 @@ updates.
785
784
  synthesize local validation artifacts from general knowledge. The handoff to
786
785
  Message Drafting should pass lean basis only, not hashes, counts, or a long
787
786
  row-id list; the branch loads current brief/context, the full
788
- `generate-messages` prompt, all referenced message assets,
789
- `create-campaign-v2-validation`, and any validation assets it references. Do
790
- not render fallback sample, concerns, or a QA receipt on the normal happy
791
- path.
787
+ `generate-messages` prompt, all required message assets, and
788
+ `create-campaign-v2-validation`. The message recommendation handoff is
789
+ labeled Markdown, not raw JSON. Do not render fallback sample, concerns, or a
790
+ QA receipt on the normal happy path.
792
791
  6. Create the campaign shell early with the v1 brief so the user can open the
793
792
  watch link and see useful setup state immediately. Materialize the approved
794
793
  source list, copy confirmed rows into the campaign, and internally process the