@sellable/mcp 0.1.208 → 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,47 +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",
163
- "source decision and selectedLeadList/source state",
164
- "workflowTableId",
165
- "imported review-batch 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__save_rubrics"
191
- ]
192
- }
193
- },
194
153
  {
195
154
  "id": "message-generation",
196
155
  "name": "post-find-leads-message-scout",
@@ -200,16 +159,17 @@
200
159
  "target": "generate-messages",
201
160
  "inputs": [
202
161
  "campaignId",
203
- "campaignBrief",
204
- "selected source state",
205
- "selectedLeadListId",
206
162
  "workflowTableId",
207
- "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"
208
167
  ],
209
168
  "producesArtifacts": [
210
169
  "template recommendation",
211
170
  "token fill rules",
212
- "rendered sample"
171
+ "one rendered good-fill sample",
172
+ "validation status"
213
173
  ],
214
174
  "optionalProducesArtifacts": [],
215
175
  "ownership": "message strategy, proof inventory, token rules, skeptical-prospect review, and selected winner only",
@@ -231,8 +191,8 @@
231
191
  "maxTurns": 10,
232
192
  "color": "magenta",
233
193
  "tools": [
234
- "Read",
235
194
  "mcp__sellable__get_subskill_prompt",
195
+ "mcp__sellable__get_subskill_asset",
236
196
  "mcp__sellable__get_campaign",
237
197
  "mcp__sellable__get_campaign_context",
238
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}`;
@@ -86,7 +86,7 @@ export interface SourceScoutRegistryResponse {
86
86
  }
87
87
  export interface PostFindLeadsScoutRegistryResponse {
88
88
  version: number;
89
- trigger: "message_drafting_after_confirm_lead_list";
89
+ trigger: "prospect_setup_after_confirm_lead_list";
90
90
  requiredInputs?: string[];
91
91
  scouts: Array<{
92
92
  id: string;
@@ -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 Message Drafting worker name after Start Import copies confirmed source rows. Prospect filters stay inline in the parent thread in normal create-campaign runs.",
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: {},
@@ -265,19 +265,17 @@ export function getSourceScoutRegistry() {
265
265
  }
266
266
  export function getPostFindLeadsScoutRegistry() {
267
267
  const registry = readAgentRegistry();
268
- const scouts = registry.agents.filter((agent) => String(agent.kind || "") === "post-find-leads-scout" &&
269
- String(agent.target || agent.id || "") === "generate-messages");
268
+ const scouts = registry.agents.filter((agent) => String(agent.kind || "") === "post-find-leads-scout");
270
269
  return {
271
270
  version: registry.version,
272
- trigger: "message_drafting_after_confirm_lead_list",
271
+ trigger: "prospect_setup_after_confirm_lead_list",
273
272
  requiredInputs: [
274
273
  "campaignId",
275
- "campaign revision or campaignUpdatedAt",
276
- "campaignBrief",
277
- "source decision and selectedLeadList/source state",
278
274
  "workflowTableId",
279
- "compact review-batch row count and basis/hash; branch reads rows through scoped tools",
280
- "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",
281
279
  ],
282
280
  scouts: scouts.map((agent) => ({
283
281
  id: String(agent.id || ""),
@@ -308,8 +306,8 @@ export function getPostFindLeadsScoutRegistry() {
308
306
  afterAllComplete: true,
309
307
  requiredState: ["messageDraftRecommendation"],
310
308
  noFilterRequiredState: ["messageDraftRecommendation"],
311
- skipFilterRule: "leadScoringRubrics may be absent only when the user explicitly skips filters with enableICPFilters=false; messageDraftRecommendation is still required before template review.",
312
- show: ["sample_message_for_approval", "message_qa_receipt"],
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"],
313
311
  nextStage: "message-review",
314
312
  },
315
313
  messageDraftBranchContract: {
@@ -327,41 +325,38 @@ export function getPostFindLeadsScoutRegistry() {
327
325
  "startedAt",
328
326
  "updatedAt",
329
327
  "basisToken",
330
- "basis.selectedLeadListId",
331
328
  "basis.workflowTableId",
332
- "basis.reviewSampleRowCount",
333
- "basis.reviewSampleRowHash",
329
+ "basis.sampleRowIds",
334
330
  ],
335
- 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.',
336
332
  basisFields: [
337
- "campaign revision or updatedAt",
338
- "brief hash",
339
- "selectedLeadListId",
333
+ "campaignId",
340
334
  "workflowTableId",
341
- "compact initial campaign-table execution slice row count/hash",
342
- "filter choice",
343
- "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",
344
339
  ],
345
340
  messageDraftOutputFields: [
346
341
  "templateRecommendation",
347
342
  "tokenFillRules",
348
- "renderedSample",
349
- "concerns",
343
+ "renderedGoodSample",
350
344
  "revisionNotes when user feedback triggered a revision",
351
345
  "status",
352
346
  "basisStatus",
353
347
  "basisToken",
354
- "qaReceipt or validationNotes",
348
+ "approveOrReviseRecommendation",
349
+ "validationStatus only; full QA details only when blocked/retry-needed",
355
350
  "outputAt",
356
351
  "outputHash",
357
352
  "error or retry detail",
358
353
  ],
359
- 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.",
360
355
  },
361
356
  usage: {
362
- 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. Once the user answers, spawn only Message Drafting from the same campaign/table basis whenever Codex agent-launch policy is satisfied. Treat YOLO/autonomous mode as campaign-scoped permission for this single message background agent. 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 generate-messages in the parent. If permission is granted and the named custom agent is unavailable, spawn a generic gpt-5.5 xhigh Message Drafting background agent with the same campaign/table basis. If filters are chosen, do filter/rubric work inline in the parent thread while Message Drafting runs, then keep the browser on Filter Leads and show `Filters saved + waiting for message approval` while the message recommendation is reviewed. If filters are skipped, move to Messages/message review.",
363
- 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. Once the user answers, invoke only Message Drafting from the same campaign/table basis. If filters are chosen, do filter/rubric work inline in the parent thread while Message Drafting runs, then keep the browser on Filter Leads and show `Filters saved + waiting for message approval` while the message recommendation is reviewed. If filters are skipped, move to Messages/message review.",
364
- parentThreadRule: 'Message Drafting is the only normal create-campaign background agent. If post-find-leads-message-scout is available, run that compatibility agent after the filter-choice answer so it works while the parent thread handles filter/rubric setup inline. In Codex, YOLO/autonomous mode counts as campaign-scoped permission for this single message background agent; 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 generate-messages in the parent. If permission is granted and the named custom agent is unavailable, spawn a generic gpt-5.5 xhigh Message Drafting background agent with the same campaign/table basis. Do not spawn source scouts or Prospect Filters in the normal create-campaign flow. 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 spawn prompt; the branch must load the current campaign brief, campaign/table state, review rows, full generate-messages prompt, and validation/QA assets through scoped tools. The parent may run the message branch inline only if the user explicitly says to continue without a background agent; when doing so, state that message generation is running inline. 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.',
365
360
  },
366
361
  };
367
362
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.208",
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
@@ -427,9 +428,9 @@ Treat host capabilities as concrete functions, not prose conventions:
427
428
  compatibility agent or a generic `gpt-5.5` / `xhigh` Message Drafting agent.
428
429
 
429
430
  If a required interactive question function or MCP loader is missing, stop and
430
- explain the Sellable install/reload problem. Source and filter work use
431
- product-native MCP orchestration in the parent; the only normal background
432
- branch is Message Drafting.
431
+ explain the Sellable install/reload problem. Source work uses product-native MCP
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.
433
434
 
434
435
  Never narrate local draft housekeeping to the user. If you create directories,
435
436
  save drafts, write artifacts, or persist intermediate state, translate it into
@@ -745,7 +746,14 @@ updates.
745
746
  copies of this file; packaged Claude Code and Codex runs must use the MCP
746
747
  asset loader so they share the same config.
747
748
  3. Follow that prompt and workflow config exactly.
748
- 4. For message generation, keep the parent thread as a lean orchestrator and
749
+ 4. For filter and message setup, keep the parent thread as a lean orchestrator.
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
754
+ Message Drafting for template review. When filters are skipped, launch only
755
+ Message Drafting.
756
+ 5. For message generation, keep the parent thread as a lean orchestrator and
749
757
  use the `post-find-leads-message-scout` compatibility agent for Message
750
758
  Drafting whenever the host exposes it
751
759
  and the current host policy allows agent launch. The worker must load
@@ -757,7 +765,7 @@ updates.
757
765
  permission before loading the long message prompt in the parent. If
758
766
  permission is granted but the named custom agent is not
759
767
  available, spawn a generic background agent with `model: "gpt-5.5"` and
760
- `reasoning_effort: "xhigh"` using the same campaign/table basis. Do not
768
+ `reasoning_effort: "xhigh"` using the same lean campaign/table basis. Do not
761
769
  silently fall back to parent-thread message drafting; parent fallback is
762
770
  allowed only when the user explicitly says to continue without a background
763
771
  agent.
@@ -768,20 +776,23 @@ updates.
768
776
  initial campaign-table execution slice rows as the source of truth; do not read stale local
769
777
  markdown such as `message-validation.md`, inspect the database directly, or
770
778
  synthesize local validation artifacts from general knowledge. The handoff to
771
- Message Drafting should pass compact basis only, not a long row-id list; the
772
- branch loads current brief/table rows and validation assets itself.
773
- 5. Create the campaign shell early with the v1 brief so the user can open the
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
+ 6. Create the campaign shell early with the v1 brief so the user can open the
774
785
  watch link and see useful setup state immediately. Materialize the approved
775
786
  source list, copy confirmed rows into the campaign, and internally process the
776
787
  first campaign-table execution slice after the source is attached to the
777
788
  campaign; do not load prospect-setup registries/prompts before asking add
778
- filters vs skip filters. Once the user answers, launch only Message Drafting
779
- from the same campaign/table basis. If filters are approved, do filter/rubric
780
- work inline in the parent thread. 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
781
791
  sequence, or start until saved filters and the
782
792
  message template/token rules are approved. When filters are chosen, immediately
783
793
  call `mcp__sellable__update_campaign({ campaignId, enableICPFilters: true, currentStep: "create-icp-rubric", watchNarration })`
784
- so the watched app moves to Filter Rules while rubrics are drafted/saved.
794
+ so the watched app moves to Filter Rules while the parent drafts/saves
795
+ rubrics and Message Drafting runs.
785
796
  After rubrics save, keep Filter Rules visible for approval; after approval,
786
797
  move to Filter Leads and show `Filters saved + waiting for message approval`
787
798
  until the template is approved.