@sellable/mcp 0.1.209 → 0.1.210

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,20 +17,19 @@ campaign state. The main thread owns approval and campaign writes.
17
17
 
18
18
  ## Source Of Truth
19
19
 
20
- Use the live campaign inputs supplied by the parent thread:
20
+ Use the lean handoff supplied by the parent thread:
21
21
 
22
22
  - `campaignId`
23
- - campaign revision or `campaignUpdatedAt`
24
- - campaign brief summary from the parent, then the current `campaignBrief` /
25
- campaign brief content loaded through Sellable tools
26
- - selected source decision and provider state
27
- - `selectedLeadListId` or selected source list context
28
23
  - `workflowTableId`
29
- - compact initial campaign-table execution-slice basis: copied source row count,
30
- review-batch row count, and review-batch basis/hash. Do not require the
31
- parent to paste a long review-batch row-id list.
32
- - filter basis at branch start: `pending`, `use-filters`, or `skip-filters`
33
- - any already-saved fit/rubric result summaries supplied by the parent
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
29
+
30
+ 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.
34
33
 
35
34
  Do not require or hunt for `brief.md`, `lead-review.md`, or `lead-sample.json`.
36
35
  Those files are optional debug context only when the parent explicitly provides
@@ -40,34 +39,47 @@ read stale local markdown files to reconstruct campaign state.
40
39
  All live reads must come from scoped MCP/product tools by campaign and
41
40
  workspace, such as `get_campaign`, `get_campaign_context`, and
42
41
  `get_rows_minimal({ tableId: workflowTableId })`, or from equivalent parent
43
- thread payloads. Load the current campaign brief and the current review-batch
44
- rows from those tools before drafting. Reject the task as `blocked` if the
45
- campaign id, workspace, `selectedLeadListId`, `workflowTableId`, review-batch
46
- row count, or review-batch basis/hash does not match the branch input.
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.
45
+
46
+ Reference assets are packaged MCP assets. Load them only through
47
+ `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`.
47
51
 
48
- ## Required First Steps
52
+ ## Required Work Loop
49
53
 
50
- 1. Load the current campaign brief and compact campaign/table state:
51
- campaign name, `campaignId`, `selectedLeadListId`, `workflowTableId`,
52
- copied source row count, review-batch row count, review-batch basis/hash,
53
- selected source summary, filter choice, and parent-supplied brief summary.
54
- Then read the current campaign/table state through scoped Sellable tools.
55
- Do not ask the parent to paste row data or a long row-id list.
56
- 2. Load the full normal-path message prompt:
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:
57
59
 
58
60
  `get_subskill_prompt({ subskillName: "generate-messages" })`
59
61
 
60
- 3. Load the reference assets required by that prompt's Reference Asset Loading
61
- pack, including validation/QA criteria. If a required validation asset cannot
62
- load, return `blocked` or `retry-needed` instead of drafting from memory.
63
- 4. Use that prompt as the drafting and QA contract. Do not use any alternate
64
- prompt, examples-only shortcut, or create-campaign safety/checklist
65
- instructions as a substitute for the full message prompt.
66
- 5. Draft only from the current campaign brief, selected source context, and
67
- review-batch rows loaded through scoped Sellable tools.
68
- 6. Run the normal message validation/QA rules before final return. The final
69
- recommendation must include the QA pass/fail receipt, not just draft copy.
70
- 7. Keep the work provisional until the user chooses `Use Template` in Messages.
62
+ 3. Load every packaged reference asset required by that prompt's Reference Asset
63
+ Loading section with `get_subskill_asset`. If a required asset cannot load
64
+ through the MCP asset loader, return `blocked` or `retry-needed` instead of
65
+ drafting from memory.
66
+ 4. Build positioning in a compact working note: buyer, pain, product, mechanism,
67
+ proof boundary, source-use rule, and CTA.
68
+ 5. Draft 3 distinct first-message options: signal-led, product/mechanism-led,
69
+ and proof/credibility-led.
70
+ 6. Combine the strongest opener, product line, mechanism line, proof treatment,
71
+ and CTA into one reusable template.
72
+ 7. Define token fill rules and fallbacks, then render one good sample.
73
+ 8. Before returning, load the validation prompt:
74
+
75
+ `get_subskill_prompt({ subskillName: "create-campaign-v2-validation" })`
76
+
77
+ Use it only as a validation contract for the candidate message in this live
78
+ campaign branch. Do not write dry-mode artifacts. Run the final candidate
79
+ against token safety, proof safety, source safety, Thomas filters, AI tells,
80
+ single-send rule, and "would I take this call?". If it fails, revise once and
81
+ validate again.
82
+ 9. Keep the work provisional until the user chooses `Use Template` in Messages.
71
83
 
72
84
  ## Owned Output
73
85
 
@@ -76,15 +88,14 @@ Return the following to the parent thread:
76
88
  - proposed first-message template using supported `{{...}}` tokens
77
89
  - token fill rules and fallbacks
78
90
  - one rendered good-fill sample for a plausible passing campaign-table row
79
- - one omit/fallback sample when the row signal is not safe
80
- - pass/fail notes against the generate-messages quality gates
81
- - `qaReceipt` / validation notes showing token safety, proof safety, fit
82
- uncertainty, bad-fill avoidance, and "would I take this call?" judgment
83
91
  - message-draft runtime status: `ready`, `blocked`, `retry-needed`, or `stale`
84
- - basis token containing campaign revision/updatedAt, brief hash,
85
- `selectedLeadListId`, `workflowTableId`, compact execution-slice row
86
- count/hash, filter choice, and rubric/filter basis when present
87
- - output timestamp/hash and any retry/error detail
92
+ - approve-or-revise recommendation
93
+ - validation status only: `passed`, `revised-then-passed`, or `blocked`
94
+ - output timestamp/hash and any blocked/retry detail
95
+
96
+ Do not return or render `renderedFallbackSample`, `concerns`, or a full
97
+ `qaReceipt` in the normal happy path. Validation is an internal gate; summarize
98
+ only if blocked or retry-needed.
88
99
 
89
100
  Do not write local markdown/json artifacts in normal live campaign runs. Return
90
101
  the recommendation directly to the parent thread. Emit debug artifacts only when
@@ -108,23 +119,21 @@ exists and points at the current non-empty campaign-table execution slice.
108
119
  ## Basis Changes And Rewrites
109
120
 
110
121
  The first completed recommendation is the default message review candidate.
111
- Do not automatically retry or regenerate only because Prospect Filters finished,
112
- rubrics were saved, Filter Leads completed, enrichment cells populated, or more
113
- row data became available after this branch started.
114
-
115
- Treat later filter/enrichment data as optional rewrite context. If campaign id,
116
- brief hash, selected source, `selectedLeadListId`, `workflowTableId`, and
117
- execution-slice row count/hash still match, keep the initial recommendation usable
118
- and report `status: ready` with `basisStatus: "usable_initial"` or
122
+ Do not automatically retry or regenerate only because filters were saved, Filter
123
+ Leads completed, enrichment cells populated, or more row data became available
124
+ after this branch started.
125
+
126
+ Treat later filter/enrichment data as optional rewrite context. If campaign id
127
+ and `workflowTableId` still match, keep the initial recommendation usable and
128
+ report `status: ready` with `basisStatus: "usable_initial"` or
119
129
  `"enriched_rewrite_available"`. The parent thread may offer the user a choice
120
130
  to keep the initial draft or rewrite with enriched/filter data, but the rewrite
121
131
  must be explicit user opt-in.
122
132
 
123
133
  Retry or regenerate without asking only when the initial recommendation is
124
134
  missing, failed, structurally invalid, unsafe, or mismatched on campaign id,
125
- brief hash, selected source, `selectedLeadListId`, `workflowTableId`, or
126
- execution-slice row count/hash. Filter/rubric/enrichment basis drift alone is not a stale
127
- blocker.
135
+ `workflowTableId`, or provided sample rows. Filter/rubric/enrichment basis drift
136
+ alone is not a stale blocker.
128
137
 
129
138
  ## User Revision Feedback And QA
130
139
 
@@ -132,17 +141,19 @@ If the parent sends user feedback, a QA request, or a rewrite request about the
132
141
  template before `approve-message`, treat it as Message Drafting work, not a
133
142
  campaign write. Use the current `messageDraftRecommendation`, basis token/hash,
134
143
  campaign/table basis, and latest user feedback as inputs. Load or reuse the full
135
- `generate-messages` contract and validation assets, then return a revised or
136
- QA-only recommendation with:
144
+ `generate-messages` contract, all referenced assets, and
145
+ `create-campaign-v2-validation`, then return a revised or QA-only recommendation
146
+ with:
137
147
 
138
148
  - revised proposed template
139
149
  - what changed and why
140
150
  - token fill rule/fallback changes, if any
141
151
  - one rendered good-fill sample
142
- - `qaReceipt` with pass/fail notes against the loaded validation assets
143
- - pass/fail notes against the same quality gates
152
+ - validation status: `passed`, `revised-then-passed`, or `blocked`
144
153
  - updated output timestamp/hash and basis token
145
154
 
155
+ Do not return a full QA receipt unless the result is blocked or retry-needed.
156
+
146
157
  Keep the revision grounded in the same source/list/table rows unless the parent
147
158
  explicitly supplies a new selected list or review slice. Do not call
148
159
  `update_campaign_brief`, do not persist the template, and do not approve your
@@ -201,20 +212,18 @@ enablement`, or omit it.
201
212
  Return a concise status with:
202
213
 
203
214
  - prompt basis loaded: `generate-messages`
215
+ - validation prompt loaded: `create-campaign-v2-validation`
204
216
  - live campaign basis used
205
217
  - proposed template
206
218
  - token fill rules/fallbacks
207
219
  - one rendered passing-row sample
208
- - one rendered omit/fallback sample
209
- - quality-gate pass/fail summary
210
220
  - whether final template review is ready or needs revision
211
221
 
212
222
  When the parent will show the recommendation in chat, keep the customer-facing
213
223
  message review lightweight. Format only the approval target and one strong
214
- good-fill example as Markdown with distinct copy blocks. Keep token rules,
215
- omit/fallback examples, and bad-fill avoidance notes in your internal
216
- recommendation so the parent can persist them to the campaign brief after
217
- approval; do not print them in the default chat approval packet.
224
+ good-fill example as Markdown with distinct copy blocks. Keep validation notes,
225
+ bad-fill avoidance notes, and QA details internal unless blocked; do not print
226
+ them in the default chat approval packet.
218
227
 
219
228
  ````markdown
220
229
  ## Message Template
@@ -150,50 +150,6 @@
150
150
  ]
151
151
  }
152
152
  },
153
- {
154
- "id": "filter-leads",
155
- "name": "post-find-leads-filter-scout",
156
- "kind": "post-find-leads-scout",
157
- "promptFile": "post-find-leads-filter-scout.md",
158
- "displayName": "Prospect Filters",
159
- "target": "filter-leads",
160
- "inputs": [
161
- "campaignId",
162
- "campaignBrief summary plus branch-loaded current campaignBrief",
163
- "source decision and selectedLeadList/source state",
164
- "workflowTableId",
165
- "compact review-batch count/hash or branch-loaded review rows"
166
- ],
167
- "producesArtifacts": [],
168
- "optionalProducesArtifacts": [],
169
- "ownership": "prospect-fit criteria, false-positive patterns, keep/exclude rules, ability-to-pay checks, and production rubric translation only",
170
- "codex": {
171
- "description": "Prospect Filters worker for campaign-backed fit criteria and rubric persistence after review-batch import and filter approval.",
172
- "model": "gpt-5.5",
173
- "modelReasoningEffort": "high",
174
- "sandboxMode": "read-only",
175
- "nicknameCandidates": [
176
- "Prospect Filters",
177
- "Fit Criteria",
178
- "Rubric Builder"
179
- ]
180
- },
181
- "claude": {
182
- "description": "Use proactively as Prospect Filters after review-batch import and filter approval to persist campaign rubrics from campaign state.",
183
- "model": "inherit",
184
- "background": true,
185
- "maxTurns": 8,
186
- "color": "yellow",
187
- "tools": [
188
- "mcp__sellable__get_subskill_prompt",
189
- "mcp__sellable__get_subskill_asset",
190
- "mcp__sellable__get_campaign",
191
- "mcp__sellable__get_campaign_context",
192
- "mcp__sellable__get_rows_minimal",
193
- "mcp__sellable__save_rubrics"
194
- ]
195
- }
196
- },
197
153
  {
198
154
  "id": "message-generation",
199
155
  "name": "post-find-leads-message-scout",
@@ -203,16 +159,17 @@
203
159
  "target": "generate-messages",
204
160
  "inputs": [
205
161
  "campaignId",
206
- "campaignBrief",
207
- "selected source state",
208
- "selectedLeadListId",
209
162
  "workflowTableId",
210
- "imported review-batch rows"
163
+ "concise brief summary",
164
+ "concise source summary/source-use rule",
165
+ "3-5 sample workflow-table rows",
166
+ "optional campaignName, selectedLeadListId, filter choice"
211
167
  ],
212
168
  "producesArtifacts": [
213
169
  "template recommendation",
214
170
  "token fill rules",
215
- "rendered sample"
171
+ "one rendered good-fill sample",
172
+ "validation status"
216
173
  ],
217
174
  "optionalProducesArtifacts": [],
218
175
  "ownership": "message strategy, proof inventory, token rules, skeptical-prospect review, and selected winner only",
@@ -234,8 +191,8 @@
234
191
  "maxTurns": 10,
235
192
  "color": "magenta",
236
193
  "tools": [
237
- "Read",
238
194
  "mcp__sellable__get_subskill_prompt",
195
+ "mcp__sellable__get_subskill_asset",
239
196
  "mcp__sellable__get_campaign",
240
197
  "mcp__sellable__get_campaign_context",
241
198
  "mcp__sellable__get_rows_minimal"
@@ -660,12 +660,10 @@ function analyzeFilterChoiceSample(sampleRows) {
660
660
  const fitRatio = fitCount / sampleCount;
661
661
  const cleanupRatio = cleanupCount / sampleCount;
662
662
  const adjacentRatio = adjacentIndexes.length / sampleCount;
663
- const maxCleanRiskCount = Math.max(2, Math.floor(sampleCount * 0.12));
664
- const recommendation = fitRatio >= 0.75 &&
665
- cleanupCount <= maxCleanRiskCount &&
666
- adjacentRatio <= 0.3
663
+ const allReviewedRowsLookFit = fitCount === sampleCount && cleanupCount === 0;
664
+ const recommendation = allReviewedRowsLookFit && adjacentRatio <= 0.3
667
665
  ? "skip"
668
- : fitRatio >= 0.6 && cleanupRatio <= 0.3
666
+ : fitRatio >= 0.75 && cleanupRatio <= 0.3
669
667
  ? "light-filter"
670
668
  : "add-filter";
671
669
  return {
@@ -697,17 +695,20 @@ function buildFilterChoiceWatchNarration({ sourceLeadCount, reviewRowCount, samp
697
695
  : "Sample rows were not available to inspect, so this is a manual filter decision.";
698
696
  const fitExamples = formatExamples("Fit examples:", assessment.strongExamples);
699
697
  const riskExamples = formatExamples("Cleanup examples:", assessment.riskExamples);
698
+ const lightFilterReason = cleanupCount > 0
699
+ ? `${cleanupCount} of ${assessment.sampleCount} need cleanup or manual review`
700
+ : `${assessment.adjacentCount} of ${assessment.sampleCount} look adjacent instead of clear target-role fits`;
700
701
  const headline = assessment.recommendation === "skip"
701
- ? "Filtering may not be needed"
702
+ ? "Filters optional for clean sample"
702
703
  : assessment.recommendation === "light-filter"
703
704
  ? "I recommend light cleanup filters"
704
705
  : assessment.recommendation === "manual-review"
705
706
  ? "Review filters or skip"
706
707
  : "I recommend adding filters";
707
708
  const agentIntent = assessment.recommendation === "skip"
708
- ? `Codex is not recommending filters because the sample already looks clean. ${fitExamples} Add filters only for a narrow exclusion.`
709
+ ? `Codex is not recommending filters because every reviewed row already looks like a target-role fit. ${fitExamples} Add filters only if the user wants an extra narrow exclusion.`
709
710
  : assessment.recommendation === "light-filter"
710
- ? `Codex is recommending light filters because most rows fit, but ${cleanupCount} of ${assessment.sampleCount} look adjacent, unknown, or risky. ${riskExamples}`
711
+ ? `Codex is recommending light filters because the sample is strong but not perfectly clean: ${lightFilterReason}. ${riskExamples}`
711
712
  : assessment.recommendation === "manual-review"
712
713
  ? "Codex could not inspect the review rows, so it is pausing for a manual filter decision instead of assuming filters are required."
713
714
  : `Codex is recommending filters because ${cleanupCount} of ${assessment.sampleCount} sampled rows look adjacent, unknown, or risky before message review. ${riskExamples}`;
@@ -157,7 +157,7 @@ export const promptToolDefinitions = [
157
157
  },
158
158
  {
159
159
  name: "get_post_find_leads_scout_registry",
160
- description: "Return the canonical Sellable Prospect Filters and Message Drafting worker names after Start Import copies confirmed source rows.",
160
+ description: "Return the canonical Sellable Message Drafting worker name after Start Import copies confirmed source rows. Normal create-campaign uses only this one post-import background agent.",
161
161
  inputSchema: {
162
162
  type: "object",
163
163
  properties: {},
@@ -271,12 +271,11 @@ export function getPostFindLeadsScoutRegistry() {
271
271
  trigger: "prospect_setup_after_confirm_lead_list",
272
272
  requiredInputs: [
273
273
  "campaignId",
274
- "campaign revision or campaignUpdatedAt",
275
- "campaignBrief",
276
- "source decision and selectedLeadList/source state",
277
274
  "workflowTableId",
278
- "compact review-batch row count and basis/hash; branch reads rows through scoped tools",
279
- "filter choice and filter/rubric basis when present",
275
+ "concise brief summary",
276
+ "concise source summary and source-use rule",
277
+ "3-5 sample workflow-table rows with rowId/name/title/company/signal",
278
+ "optional selectedLeadListId, campaignName, and filter choice",
280
279
  ],
281
280
  scouts: scouts.map((agent) => ({
282
281
  id: String(agent.id || ""),
@@ -305,14 +304,10 @@ export function getPostFindLeadsScoutRegistry() {
305
304
  })),
306
305
  joinGate: {
307
306
  afterAllComplete: true,
308
- requiredState: ["leadScoringRubrics", "messageDraftRecommendation"],
307
+ requiredState: ["messageDraftRecommendation"],
309
308
  noFilterRequiredState: ["messageDraftRecommendation"],
310
- skipFilterRule: "leadScoringRubrics may be absent only when the user explicitly skips filters with enableICPFilters=false; messageDraftRecommendation is still required before template review.",
311
- show: [
312
- "readable_filters_with_reasons",
313
- "sample_message_for_approval",
314
- "message_qa_receipt",
315
- ],
309
+ skipFilterRule: "Filters are parent-thread MCP work. The only background worker is Message Drafting; messageDraftRecommendation is required before template review.",
310
+ show: ["sample_message_for_approval"],
316
311
  nextStage: "message-review",
317
312
  },
318
313
  messageDraftBranchContract: {
@@ -330,41 +325,38 @@ export function getPostFindLeadsScoutRegistry() {
330
325
  "startedAt",
331
326
  "updatedAt",
332
327
  "basisToken",
333
- "basis.selectedLeadListId",
334
328
  "basis.workflowTableId",
335
- "basis.reviewSampleRowCount",
336
- "basis.reviewSampleRowHash",
329
+ "basis.sampleRowIds",
337
330
  ],
338
- promptRequired: 'Load current campaign brief/table state through scoped tools, then get_subskill_prompt({ subskillName: "generate-messages" }); the full generate-messages prompt and its Reference Asset Loading pack, including message validation/QA assets requested by that prompt, are required inside the Message Drafting branch for normal drafting, QA, and user-requested rewrites. If required assets cannot be loaded, return blocked/retry-needed instead of drafting from prompt memory.',
331
+ promptRequired: 'Load current campaign brief/table state through scoped tools, then get_subskill_prompt({ subskillName: "generate-messages" }) for all chunks. Load every asset named in the generate-messages Reference Asset Loading pack through get_subskill_asset. 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.',
339
332
  basisFields: [
340
- "campaign revision or updatedAt",
341
- "brief hash",
342
- "selectedLeadListId",
333
+ "campaignId",
343
334
  "workflowTableId",
344
- "compact initial campaign-table execution slice row count/hash",
345
- "filter choice",
346
- "filter/rubric basis when present",
335
+ "concise brief summary",
336
+ "concise source summary/source-use rule",
337
+ "3-5 sample workflow-table rows",
338
+ "optional selectedLeadListId and filter choice",
347
339
  ],
348
340
  messageDraftOutputFields: [
349
341
  "templateRecommendation",
350
342
  "tokenFillRules",
351
- "renderedSample",
352
- "concerns",
343
+ "renderedGoodSample",
353
344
  "revisionNotes when user feedback triggered a revision",
354
345
  "status",
355
346
  "basisStatus",
356
347
  "basisToken",
357
- "qaReceipt or validationNotes",
348
+ "approveOrReviseRecommendation",
349
+ "validationStatus only; full QA details only when blocked/retry-needed",
358
350
  "outputAt",
359
351
  "outputHash",
360
352
  "error or retry detail",
361
353
  ],
362
- reusePolicy: "The first completed Message Drafting recommendation remains the default review candidate. Later Prospect 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/brief/source/list/table/review-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.",
354
+ 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.",
363
355
  },
364
356
  usage: {
365
- 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. If filters are chosen, spawn Prospect Filters and Message Drafting from the same campaign/table basis whenever Codex agent-launch policy is satisfied, then the parent waits for Prospect Filters first, verifies save_rubrics succeeded, asks filter approval, and only then joins Message Drafting for template review. If filters are skipped, spawn only Message Drafting. Treat YOLO/autonomous mode as campaign-scoped permission for these post-import workers. 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 long filter/message prompts 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 campaign/table basis.",
366
- 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. If filters are chosen, invoke Prospect Filters and Message Drafting from the same campaign/table basis; parent waits for Prospect Filters first, verifies save_rubrics succeeded, asks filter approval, then joins Message Drafting. If filters are skipped, invoke only Message Drafting and move to Messages/message review.",
367
- parentThreadRule: 'Post-import background work is limited to Prospect Filters and Message Drafting; source scouts stay out of the normal create-campaign path. If filters are chosen and the workers are available, launch post-find-leads-filter-scout and post-find-leads-message-scout after the filter-choice answer. The parent thread remains the orchestrator: wait for Prospect Filters first, require save_rubrics success or persist the returned production rubrics, keep the browser on Filter Rules, ask filter approval, then move to Filter Leads and join/wait for Message Drafting. Do not move into message review, queue cells, or call update_campaign_brief until saved filters are approved and messageDraftRecommendation is ready. If filters are skipped, launch only Message Drafting. In Codex, YOLO/autonomous mode counts as campaign-scoped permission for these post-import workers; 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 long filter/message prompts 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 compact: campaign identity/name, brief summary, source summary, selectedLeadListId, workflowTableId, copied source row count, review-batch row count/hash, and filter choice. Do not paste full reviewBatchRowIds, row data, or local debug artifacts into the message spawn prompt; the message branch must load the current campaign brief, campaign/table state, review rows, full generate-messages prompt, and validation/QA assets through scoped tools. Local markdown/json files are not normal-path inputs. 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, must load get_subskill_prompt({ subskillName: "generate-messages" }) and its Reference Asset Loading plus message validation/QA assets inside the branch or explicitly approved inline fallback, 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 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, basis token, 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. 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 and QA assets 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.',
357
+ 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.",
358
+ 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.",
359
+ parentThreadRule: 'The only normal post-import background worker is Message Drafting; source scouts and separate filter workers stay out of the normal create-campaign path. 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, every referenced asset through get_subskill_asset, and before returning get_subskill_prompt({ subskillName: "create-campaign-v2-validation" }) for the internal validation gate. 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, 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.',
368
360
  },
369
361
  };
370
362
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.209",
3
+ "version": "0.1.210",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -279,14 +279,15 @@ Messages/message review. Enrichment/filtering and Generate Message cells wait
279
279
  for message approval. AI Generated is an explicit opt-out from the template
280
280
  path.
281
281
 
282
- The Message Drafting handoff must stay compact. Include campaign identity,
283
- campaign name, `selectedLeadListId`, `workflowTableId`, copied source row count,
284
- review-batch row count, review-batch basis/hash, filter choice, source summary,
285
- and a concise campaign brief summary. Do not paste the full review-batch row ID
286
- list or row data into the spawn prompt. Message Drafting must load the current
287
- campaign brief, campaign/table state, and review-batch rows through Sellable
288
- tools, then load the normal message validation/QA rules and run a QA pass before
289
- returning its concise review-ready recommendation.
282
+ The Message Drafting handoff must stay lean. Include only `campaignId`,
283
+ `workflowTableId`, a concise brief summary, concise source summary/source-use
284
+ rule, and 3-5 sample workflow-table rows with `rowId`, name, title, company, and
285
+ signal. Optional: campaign name, `selectedLeadListId`, and filter choice. Do not
286
+ paste copied row counts, brief hashes, review-batch hashes, full row ID lists,
287
+ broad row data, or local debug artifacts into the spawn prompt. Message Drafting
288
+ must load the current campaign brief/context, full `generate-messages` prompt,
289
+ all referenced assets, and `create-campaign-v2-validation`; validation is an
290
+ internal gate before it returns the concise review-ready recommendation.
290
291
 
291
292
  Use rendered Markdown for user review surfaces, not fenced code blocks. Keep
292
293
  lines short, use indexed section labels and bullets, and translate internal
@@ -421,19 +422,15 @@ Treat host capabilities as concrete functions, not prose conventions:
421
422
  not call it in the normal create-campaign source path.
422
423
  - `load_post_find_leads_scout_registry`: call
423
424
  `mcp__sellable__get_post_find_leads_scout_registry({})` after source
424
- import and before dispatching Prospect Filters / Message Drafting.
425
- - `launch_prospect_filters`: Claude Code uses `Task` with `subagent_type`
426
- `post-find-leads-filter-scout` when filters are chosen; Codex uses the
427
- returned compatibility agent. Prospect Filters must save or return production
428
- rubrics before message review can proceed.
425
+ import and before dispatching Message Drafting only.
429
426
  - `launch_message_drafting`: Claude Code uses `Task` with `subagent_type`
430
427
  `post-find-leads-message-scout` when listed; Codex uses the returned
431
428
  compatibility agent or a generic `gpt-5.5` / `xhigh` Message Drafting agent.
432
429
 
433
430
  If a required interactive question function or MCP loader is missing, stop and
434
431
  explain the Sellable install/reload problem. Source work uses product-native MCP
435
- orchestration in the parent; the only normal post-import background branches are
436
- Prospect Filters and Message Drafting.
432
+ orchestration in the parent; filters also stay in the parent with MCP tools. The
433
+ only normal post-import background branch is Message Drafting.
437
434
 
438
435
  Never narrate local draft housekeeping to the user. If you create directories,
439
436
  save drafts, write artifacts, or persist intermediate state, translate it into
@@ -750,10 +747,10 @@ updates.
750
747
  asset loader so they share the same config.
751
748
  3. Follow that prompt and workflow config exactly.
752
749
  4. For filter and message setup, keep the parent thread as a lean orchestrator.
753
- When filters are chosen, use `post-find-leads-filter-scout` for Prospect
754
- Filters and `post-find-leads-message-scout` for Message Drafting. The parent
755
- waits for Prospect Filters first, verifies `save_rubrics` succeeded or saves
756
- returned production rubrics itself, asks filter approval, and only then joins
750
+ The only normal background agent is `post-find-leads-message-scout` for
751
+ Message Drafting. When filters are chosen, launch Message Drafting, then keep
752
+ filters in the parent thread: load `references/filter-leads.md`, draft
753
+ production rubrics, call `save_rubrics`, ask filter approval, and then join
757
754
  Message Drafting for template review. When filters are skipped, launch only
758
755
  Message Drafting.
759
756
  5. For message generation, keep the parent thread as a lean orchestrator and
@@ -768,7 +765,7 @@ updates.
768
765
  permission before loading the long message prompt in the parent. If
769
766
  permission is granted but the named custom agent is not
770
767
  available, spawn a generic background agent with `model: "gpt-5.5"` and
771
- `reasoning_effort: "xhigh"` using the same campaign/table basis. Do not
768
+ `reasoning_effort: "xhigh"` using the same lean campaign/table basis. Do not
772
769
  silently fall back to parent-thread message drafting; parent fallback is
773
770
  allowed only when the user explicitly says to continue without a background
774
771
  agent.
@@ -779,21 +776,23 @@ updates.
779
776
  initial campaign-table execution slice rows as the source of truth; do not read stale local
780
777
  markdown such as `message-validation.md`, inspect the database directly, or
781
778
  synthesize local validation artifacts from general knowledge. The handoff to
782
- Message Drafting should pass compact basis only, not a long row-id list; the
783
- branch loads current brief/table rows and validation assets itself.
779
+ Message Drafting should pass lean basis only, not hashes, counts, or a long
780
+ row-id list; the branch loads current brief/context, the full
781
+ `generate-messages` prompt, all referenced assets, and
782
+ `create-campaign-v2-validation` itself. Do not render fallback sample,
783
+ concerns, or a QA receipt on the normal happy path.
784
784
  6. Create the campaign shell early with the v1 brief so the user can open the
785
785
  watch link and see useful setup state immediately. Materialize the approved
786
786
  source list, copy confirmed rows into the campaign, and internally process the
787
787
  first campaign-table execution slice after the source is attached to the
788
788
  campaign; do not load prospect-setup registries/prompts before asking add
789
- filters vs skip filters. Once the user answers, launch Prospect Filters plus
790
- Message Drafting when filters are chosen, or only Message Drafting when
791
- filters are skipped. Do not queue workflow cells, attach a
789
+ filters vs skip filters. Once the user answers, launch only Message Drafting.
790
+ If filters are chosen, draft/save filters in the parent thread. Do not queue workflow cells, attach a
792
791
  sequence, or start until saved filters and the
793
792
  message template/token rules are approved. When filters are chosen, immediately
794
793
  call `mcp__sellable__update_campaign({ campaignId, enableICPFilters: true, currentStep: "create-icp-rubric", watchNarration })`
795
- so the watched app moves to Filter Rules while Prospect Filters drafts/saves
796
- rubrics.
794
+ so the watched app moves to Filter Rules while the parent drafts/saves
795
+ rubrics and Message Drafting runs.
797
796
  After rubrics save, keep Filter Rules visible for approval; after approval,
798
797
  move to Filter Leads and show `Filters saved + waiting for message approval`
799
798
  until the template is approved.