@sellable/mcp 0.1.91 → 0.1.92

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.
@@ -20,11 +20,11 @@ Required first steps:
20
20
  1. Read the three required inputs.
21
21
  2. Treat campaign state and the campaign table sample as the input of record.
22
22
  Disk files are context/debug aids, not durable state.
23
- 3. Use the embedded Message Review Fast Path below. Do not load the full
24
- long-form `generate-messages` subskill in the normal path. Load it only when
25
- the fast path is missing a needed campaign-specific rule, the user explicitly
26
- asks for deep calibration, or the first fast-path draft fails quality gates
27
- and no local reference explains how to repair it.
23
+ 3. Use the embedded Message Review Safety Gate below. Do not load the full
24
+ long-form `generate-messages` subskill in this `create-campaign-v2` path. If
25
+ a needed rule is missing or the draft fails quality gates, return
26
+ `revise-messaging` with the exact failure instead of pulling the long prompt
27
+ into this worker.
28
28
 
29
29
  Owned outputs:
30
30
 
@@ -46,8 +46,8 @@ Do not write or modify:
46
46
 
47
47
  Process:
48
48
 
49
- 1. Run the embedded fast-path workflow in dry mode from the approved brief,
50
- lead-review source decision, and `lead-sample.json`.
49
+ 1. Run the embedded message-review safety-gate workflow in dry mode from the
50
+ approved brief, lead-review source decision, and `lead-sample.json`.
51
51
  2. Use `lead-sample.json` as the only lead sample source. Do not fetch new
52
52
  prospects or invent richer row signals.
53
53
  3. Build proof inventory, token fill rules, token adherence, angle drafts,
@@ -69,7 +69,8 @@ Process:
69
69
  Return a concise final status with:
70
70
 
71
71
  - artifacts written
72
- - whether embedded fast-path rules were used or the full fallback was needed
72
+ - whether the embedded message-review safety-gate rules passed or returned
73
+ `revise-messaging`
73
74
  - lead sample basis used
74
75
  - proposed template and one sample message
75
76
  - selected winner summary
@@ -78,12 +79,12 @@ Return a concise final status with:
78
79
  Quality bar:
79
80
 
80
81
  - Do not synthesize a lightweight message from general knowledge. The artifact
81
- must prove the embedded fast-path workflow ran.
82
+ must prove the embedded message-review safety-gate workflow ran.
82
83
  - Message generation can start before `lead-filter.md`, but message review
83
84
  cannot start until the parent verifies the selected basis rows still pass the
84
85
  final filter.
85
86
 
86
- ## Embedded Message Review Fast Path
87
+ ## Embedded Message Review Safety Gate
87
88
 
88
89
  Use this campaign-launch subset to produce a truthful first-send message,
89
90
  rendered token examples, and a decision without loading the full long-form
@@ -26,6 +26,17 @@ function buildWatchUrl(config, redirect) {
26
26
  : "";
27
27
  return `${config.apiUrl}/auth/continue?token=${config.token}&redirect=${redirect}${workspaceParam}`;
28
28
  }
29
+ function isLinkedInProfileUrl(input) {
30
+ try {
31
+ const url = new URL(input);
32
+ const host = url.hostname.toLowerCase();
33
+ return ((host === "linkedin.com" || host.endsWith(".linkedin.com")) &&
34
+ /^\/in\/[^/]+\/?$/i.test(url.pathname));
35
+ }
36
+ catch {
37
+ return false;
38
+ }
39
+ }
29
40
  export const campaignToolDefinitions = [
30
41
  {
31
42
  name: "get_campaigns",
@@ -613,9 +624,10 @@ export async function createCampaign(input) {
613
624
  if (!hasClientProspectId && !senderLinkedinUrl) {
614
625
  missing.push("clientProspectId or senderLinkedinUrl");
615
626
  }
616
- // Cheap URL sanity check on senderLinkedinUrl when supplied.
617
- if (senderLinkedinUrl && !senderLinkedinUrl.includes("linkedin.com")) {
618
- throw new Error("VALIDATION_ERROR: senderLinkedinUrl must be a LinkedIn URL (must contain 'linkedin.com'). Got: " +
627
+ // Cheap URL sanity check on senderLinkedinUrl when supplied. This input is a
628
+ // profile bootstrap fallback; company pages should use clientProspectId.
629
+ if (senderLinkedinUrl && !isLinkedInProfileUrl(senderLinkedinUrl)) {
630
+ throw new Error("VALIDATION_ERROR: senderLinkedinUrl must be a LinkedIn profile URL like https://www.linkedin.com/in/name/. Company pages require clientProspectId or a discovered profile URL. Got: " +
619
631
  senderLinkedinUrl);
620
632
  }
621
633
  if (missing.length > 0) {
@@ -16,6 +16,14 @@ export function markResearchPromptLoaded(mode = "generic", subskillName) {
16
16
  : mode === "prospect"
17
17
  ? "research-prospect"
18
18
  : "research");
19
+ const existing = researchPromptStates[mode];
20
+ // Re-loading the same research prompt is a context-management detail, not
21
+ // new research. Preserve the original load timestamp so a completed research
22
+ // marker does not become stale just because the host refreshed instructions.
23
+ if (existing?.subskillName === normalizedSubskillName) {
24
+ latestResearchPromptState = existing;
25
+ return existing;
26
+ }
19
27
  const state = {
20
28
  loadedAt: new Date().toISOString(),
21
29
  mode,
@@ -289,7 +289,7 @@ export function getPostFindLeadsScoutRegistry() {
289
289
  usage: {
290
290
  codex: "After the user approves or auto-confirms the lead source, spawn both returned scout `name` values in one assistant turn only when the current Codex host exposes those custom agents.",
291
291
  claude: "After lead source approval, invoke both returned Task/Agent subagents in one assistant message only when the current Claude session lists those agents, so filter-leads and message generation run concurrently.",
292
- parentThreadRule: "Named agents are optional acceleration. If they are absent, do not customer-surface install status; the main thread still orchestrates filter and message branches from brief.md, lead-review.md, and lead-sample.json. The message branch should use the baked-in message-scout prompt or the create-campaign-v2 message-review fast-path asset, not the full long generate-messages prompt in the normal path. Join before message review.",
292
+ parentThreadRule: "Named agents are optional acceleration. If they are absent, do not customer-surface install status; the main thread still orchestrates filter and message branches from brief.md, lead-review.md, and lead-sample.json. The message branch should use the baked-in message-scout prompt or the create-campaign-v2 message-review safety gate asset, not the full long generate-messages prompt in the normal path. Join before message review.",
293
293
  },
294
294
  };
295
295
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.91",
3
+ "version": "0.1.92",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -490,14 +490,17 @@ updates.
490
490
  4. For message generation, use the `post-find-leads-message-scout` agent when
491
491
  available; its prompt carries the campaign-launch message rules. In the
492
492
  parent-thread fallback, load
493
- `mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-fast-path.md" })`.
493
+ `mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-safety-gate.md" })`.
494
+ Do not load the full long-form `generate-messages` subskill in this
495
+ create-campaign path; if the safety gate cannot safely approve the draft,
496
+ route to revise messaging with the concrete failure.
494
497
  Do not synthesize `message-validation.md` from the brief, lead review, or
495
498
  general knowledge.
496
499
  5. Create the campaign shell early with the v1 brief so the user can open the
497
500
  watch link and see useful setup state immediately. Import only the first
498
501
  bounded review batch after the source is attached to the campaign; do not
499
502
  queue workflow cells, attach a sequence, or start until
500
- `message-validation.md` proves the fast-path message workflow ran,
503
+ `message-validation.md` proves the message-review safety-gate workflow ran,
501
504
  `message-review.md` approves the template, rubrics are saved, and the
502
505
  approved message set is synced into the campaign brief.
503
506
  6. Keep `selectedLeadListId` as the source list and `workflowTableId` as the
@@ -189,7 +189,10 @@ Validated draft directory:
189
189
  it as the preferred `create_campaign` identity input. If it includes a
190
190
  LinkedIn profile URL, keep that URL as `senderLinkedinUrl` so the backend can
191
191
  resolve/materialize the sender prospect when the watchable campaign shell is
192
- created. Do not require a connected sender before shell creation.
192
+ created. Do not pass a LinkedIn company page as `senderLinkedinUrl`; for a
193
+ company-only identity, use `clientProspectId` if already materialized or do
194
+ one lightweight lookup to find the relevant founder/operator profile. Do not
195
+ require a connected sender before shell creation.
193
196
  - If the user supplied a LinkedIn profile, website, domain, company name, or
194
197
  explicit client prospect identity in the invocation, do one lightweight lookup
195
198
  first:
@@ -217,7 +220,8 @@ Validated draft directory:
217
220
  profile, call `fetch_linkedin_profile` and infer the current or most recent
218
221
  company from the profile. For a company website, call `fetch_company` when
219
222
  possible, otherwise one web lookup. If a LinkedIn profile URL is available,
220
- retain it as `senderLinkedinUrl` for `create_campaign`; if a
223
+ retain it as `senderLinkedinUrl` for `create_campaign`; if only a LinkedIn
224
+ company page is available, do not pass it as `senderLinkedinUrl`. If a
221
225
  `clientProspectId` is available, pass that instead.
222
226
 
223
227
  After the user confirms the campaign identity, check whether the company
@@ -424,6 +428,10 @@ message we should test.`
424
428
  - `brief.md` is the single user-facing debug copy of the brief. The
425
429
  `CampaignOffer.campaignBrief` field is the stable downstream thesis source.
426
430
  - `lead-review.md` and `lead-sample.json` are the required outputs of `find leads`.
431
+ `lead-review.md` is customer-readable: describe source paths as provider
432
+ lanes checked (Signals, Sales Nav, Prospeo) and never include custom agent
433
+ names, host availability, install state, allowed-tool state, or fallback
434
+ implementation details.
427
435
  - `lead-filter.md` is the primary output of `filter leads`.
428
436
  - `rubric.json` is optional and secondary to `lead-filter.md`.
429
437
  - `message-prep.md` is an optional speed artifact produced by the explicit
@@ -1058,21 +1066,22 @@ Do not:
1058
1066
  Step 3 is orchestrated by the main thread and executed either by the
1059
1067
  `post-find-leads-message-scout` worker or by the parent-thread fallback. The
1060
1068
  worker carries the campaign-launch message rules in its agent prompt. The
1061
- parent-thread fallback must load the small fast-path reference before writing
1069
+ parent-thread fallback must load the small safety-gate reference before writing
1062
1070
  message artifacts:
1063
1071
 
1064
1072
  ```
1065
- mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-fast-path.md" })
1073
+ mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-safety-gate.md" })
1066
1074
  ```
1067
1075
 
1068
- Do not force the main thread to load the full long-form `generate-messages`
1069
- subskill in the normal path. Load the full `generate-messages` subskill only
1070
- when the fast path is missing a needed campaign-specific rule, the user
1071
- explicitly asks for deep calibration, or the first fast-path draft fails quality
1072
- gates and no local reference explains how to repair it.
1076
+ Do not load the full long-form `generate-messages` subskill in
1077
+ `create-campaign-v2`. The safety-gate asset is a parent-thread fallback for hosts
1078
+ that cannot launch `post-find-leads-message-scout`, not the preferred route. If
1079
+ the safety gate is missing a needed campaign-specific rule or the draft fails
1080
+ quality gates, stop at `revise-messaging` with the exact failure instead of
1081
+ pulling the long prompt into the main thread.
1073
1082
 
1074
1083
  Do NOT proceed to Step 4 (message review gate) unless `message-validation.md`
1075
- contains the fast-path required sections, a raw sendable Selected Winner, and an
1084
+ contains the safety-gate required sections, a raw sendable Selected Winner, and an
1076
1085
  explicit single-first-send PASS. If `message-validation.md` contains post-accept
1077
1086
  DM, follow-up, second-touch, cadence, branch, or other sequence-shaped copy, do
1078
1087
  not summarize it as ready; route back to message-generation and require a
@@ -947,7 +947,7 @@
947
947
  "ownership": "proof inventory, token strategy, angle drafting, skeptical-prospect review, and selected winner only"
948
948
  }
949
949
  ],
950
- "earlyMessageStartRule": "After auto-execute-leads confirms the 10-row review batch and workflowTableId is ready, launch message-generation from brief.md, lead-review.md, lead-sample.json, and the imported campaign table sample. The message worker carries the campaign-launch message rules in its agent prompt; parent-thread fallback loads references/message-review-fast-path.md. Legacy/resume preview prep still requires at least 5 probable good-fit rows. It may run beside filter-leads, but the cascade cannot queue until save_rubrics and update_campaign_brief both succeed.",
950
+ "earlyMessageStartRule": "After auto-execute-leads confirms the 10-row review batch and workflowTableId is ready, launch message-generation from brief.md, lead-review.md, lead-sample.json, and the imported campaign table sample. The message worker carries the campaign-launch message rules in its agent prompt; parent-thread fallback loads references/message-review-safety-gate.md. Legacy/resume preview prep still requires at least 5 probable good-fit rows. It may run beside filter-leads, but the cascade cannot queue until save_rubrics and update_campaign_brief both succeed.",
951
951
  "finalMessageReconcileRule": "message-validation.md may start before lead-filter.md exists, but before message-review it must cite only imported review-batch rows that still pass lead-filter.md. If the selected winner depends on a row later excluded by lead-filter.md, revise message-generation before message review.",
952
952
  "claudeRule": "In Claude Code, launch both returned post-find-leads scouts with Task/Agent subagents in the same assistant message only when the current session lists those agent names. Do not run filter first and then message generation unless subagents/background work are unavailable.",
953
953
  "codexRule": "In Codex, launch both returned post-find-leads scout names as disjoint subagents in the same assistant turn only when the host exposes those custom agents for this run. If the host cannot spawn them, run the same branches sequentially and say so.",
@@ -1014,7 +1014,7 @@
1014
1014
  "The post-lead workstreams are disjoint: filter-leads owns lead-filter.md/rubric.json; message-generation owns message-validation.md/message-prep.md/message-candidate-drafts.md.",
1015
1015
  "message-generation can start before lead-filter.md, but message-review cannot start until both lead-filter.md and message-validation.md exist and reconcile against the same lead-sample.json.",
1016
1016
  "Do not let filter-leads create a new message sample. Do not let message-generation fetch new prospects.",
1017
- "Before writing message-validation.md, message-generation must either run in the post-find-leads-message-scout agent that carries the campaign-launch message rules in its prompt or load get_subskill_asset({ subskillName: \"create-campaign-v2\", assetPath: \"references/message-review-fast-path.md\" }) in the parent-thread fallback. Do not load the full long generate-messages prompt in the normal path.",
1017
+ "Before writing message-validation.md, message-generation must either run in the post-find-leads-message-scout agent that carries the campaign-launch message rules in its prompt or load get_subskill_asset({ subskillName: \"create-campaign-v2\", assetPath: \"references/message-review-safety-gate.md\" }) in the parent-thread fallback. Do not load the full long generate-messages prompt in create-campaign-v2; if the safety gate cannot safely approve the draft, route to revise-messaging with the concrete failure.",
1018
1018
  "Do not queue, enrich, attach sequence, or start until save_rubrics succeeds and the approved message set is synced into campaignBrief."
1019
1019
  ],
1020
1020
  "doNotAllow": [
@@ -1181,11 +1181,11 @@
1181
1181
  "onEnter": [
1182
1182
  {
1183
1183
  "action": "run_or_reconcile_subskill",
1184
- "target": "message-review-fast-path",
1184
+ "target": "message-review-safety-gate",
1185
1185
  "mode": "DRY MODE",
1186
1186
  "sampleSource": "lead-sample.json from find-leads",
1187
1187
  "toolCallRequiredBeforeArtifacts": [
1188
- "get_subskill_asset({ subskillName: \"create-campaign-v2\", assetPath: \"references/message-review-fast-path.md\" }) unless the post-find-leads-message-scout agent prompt already supplied these rules"
1188
+ "get_subskill_asset({ subskillName: \"create-campaign-v2\", assetPath: \"references/message-review-safety-gate.md\" }) unless the post-find-leads-message-scout agent prompt already supplied these rules"
1189
1189
  ],
1190
1190
  "skipIfFreshArtifactExists": "message-validation.md",
1191
1191
  "reconcileWith": "lead-filter.md; lead-sample.json remains the sample source"
@@ -1204,18 +1204,17 @@
1204
1204
  "message-validation.md"
1205
1205
  ],
1206
1206
  "allowedTools": [
1207
- "get_subskill_prompt",
1208
1207
  "get_subskill_asset",
1209
1208
  "AskUserQuestion",
1210
1209
  "request_user_input"
1211
1210
  ],
1212
1211
  "toolRules": [
1213
- "Before writing message-validation.md, message-review.md, or a message-review AskUserQuestion, the current run must either execute inside the post-find-leads-message-scout agent that carries the campaign-launch message rules in its prompt or load get_subskill_asset({ subskillName: \"create-campaign-v2\", assetPath: \"references/message-review-fast-path.md\" }) in the parent-thread fallback.",
1212
+ "Before writing message-validation.md, message-review.md, or a message-review AskUserQuestion, the current run must either execute inside the post-find-leads-message-scout agent that carries the campaign-launch message rules in its prompt or load get_subskill_asset({ subskillName: \"create-campaign-v2\", assetPath: \"references/message-review-safety-gate.md\" }) in the parent-thread fallback.",
1214
1213
  "Lead Sample Basis must cite rows from lead-sample.json produced by find-leads. lead-filter.md only gates those rows; it is not a source for a new sample.",
1215
1214
  "Do not hand-write message-validation.md from message-prep.md, message-candidate-drafts.md, or general campaign knowledge.",
1216
- "message-validation.md must prove the fast-path workflow ran: Gold Standard Strategy Map, Campaign Element Pool, Current Campaign Translation, Token Fill Rules, Token Adherence Table, Angle Drafts, Kill / Combine Review, Finalizer Pass, Gold-Standard Quality Gate, Skeptical Prospect Review, Winner Gate, and a raw sendable Selected Winner are required before message-review can recommend approve-message.",
1217
- "If the Codex-hosted output is plausible but weaker than the loaded gold-standard examples, stop at message-review with revise-messaging. Do not continue to approval or mint just because the mechanical flow worked.",
1218
- "Load the full generate-messages subskill only when the fast path is missing a needed campaign-specific rule, the user explicitly asks for deep calibration, or the first fast-path draft fails quality gates and no local reference explains how to repair it.",
1215
+ "message-validation.md must prove the message-review safety-gate workflow ran: Gold Standard Strategy Map, Campaign Element Pool, Current Campaign Translation, Token Fill Rules, Token Adherence Table, Angle Drafts, Kill / Combine Review, Finalizer Pass, Gold-Standard Quality Gate, Skeptical Prospect Review, Winner Gate, and a raw sendable Selected Winner are required before message-review can recommend approve-message.",
1216
+ "If the hosted output is plausible but weaker than the safety-gate gold-standard rules, stop at message-review with revise-messaging. Do not continue to approval or mint just because the mechanical flow worked.",
1217
+ "Do not load the full generate-messages subskill in create-campaign-v2. If the safety gate is missing a needed campaign-specific rule or the first safety-gate draft fails quality gates, route to revise-messaging with the concrete failure instead of loading the long prompt.",
1219
1218
  "The approved message set must be written back into campaignBrief before validate-sample queues the review-batch cascade."
1220
1219
  ],
1221
1220
  "doNotAllow": [
@@ -32,12 +32,14 @@ Before showing the commit gate, the draft directory must contain all of:
32
32
  - `message-validation.md`
33
33
  - `approval-packet.md`
34
34
 
35
- The current run must also have retrieved the real message-generation prompt
36
- through `get_message_prompt({ promptName: "generate-messages" })` or
37
- `get_subskill_prompt({ subskillName: "generate-messages" })` before
38
- `message-validation.md`, `approval-packet.md`, or the commit gate is written.
39
- If the message template was written directly from memory or planning artifacts,
40
- do not show the commit gate; route back to message generation.
35
+ The current run must also have retrieved message-generation rules before
36
+ `message-validation.md`, `approval-packet.md`, or the commit gate is written. In
37
+ `create-campaign-v2`, use the compact
38
+ `references/message-review-safety-gate.md` asset or the embedded
39
+ `post-find-leads-message-scout` prompt. Do not load the full long-form
40
+ `generate-messages` subskill for the hosted campaign launch path. If the message
41
+ template was written directly from memory or planning artifacts, do not show the
42
+ commit gate; route back to message generation.
41
43
 
42
44
  `rubric.json` is optional but strongly preferred — when missing, derive it from
43
45
  `lead-filter.md` in the atomic mint step.
@@ -1,14 +1,19 @@
1
- # Message Review Fast Path
1
+ # Message Review Safety Gate
2
2
 
3
- Use this reference for `create-campaign-v2` message review. It is the
4
- campaign-launch subset of `generate-messages`: enough to produce a truthful
5
- first-send message, rendered token examples, and an approval decision without
6
- loading the full long-form message-generation prompt into Claude/Codex.
3
+ Use this reference for `create-campaign-v2` message review only in two cases:
4
+ when these rules are embedded inside the `post-find-leads-message-scout` agent
5
+ prompt, or when the host cannot launch that agent and the parent thread needs a
6
+ compact fallback. It is the campaign-launch subset of `generate-messages`: enough
7
+ to prove a truthful first-send message, rendered token examples, and an approval
8
+ decision without loading the full long-form message-generation prompt into the
9
+ main Claude/Codex thread.
7
10
 
8
- Load the full `generate-messages` subskill only when the fast path is missing a
9
- needed campaign-specific rule, the user explicitly asks for deep calibration, or
10
- the first fast-path draft fails quality gates and no local reference explains
11
- how to repair it.
11
+ In a normal installed Claude/Codex session, the message scout owns these rules.
12
+ The parent-thread asset is a compatibility fallback, not a shortcut. Do not load
13
+ the full `generate-messages` subskill in this flow. If the safety gate is missing
14
+ a needed campaign-specific rule or the draft fails quality gates, stop at
15
+ `revise-messaging` with the exact missing rule/failure instead of pulling the
16
+ long prompt into the main thread.
12
17
 
13
18
  ## Required Workflow
14
19