@sellable/mcp 0.1.54 → 0.1.56

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.
@@ -57,23 +57,20 @@ turn anchored to that:
57
57
 
58
58
  Approvals only feel safe when the user can see what they are approving. Before
59
59
  any approve/revise question, show the relevant decision in plain language. For a
60
- brief approval, render the slim approval brief, not just a direction summary.
61
- Any list the user is expected to review should be rendered Markdown with short
62
- indexed sections and bullets. Avoid label-plus-paragraph blocks like
63
- `Key numbers:` followed by a dense paragraph, and never use fenced code blocks
64
- for review surfaces.
60
+ brief approval, render the brief itself, not just a direction summary.
65
61
 
66
62
  Every approval should also give the user a way to inspect the source artifact.
67
- After the readable inline content, include an `Open artifact:` line with the one
68
- key link behind the decision. Do not show long plain paths in normal chat; offer
69
- them only as a fallback if links cannot be created. The artifact link is a backup
70
- for inspection, not a replacement for showing the decision in chat.
63
+ After the readable inline content, include an `Open artifacts:` line with links
64
+ or plain paths to the files behind the decision. The artifact links are a backup
65
+ for inspection, not a replacement for showing the content in chat.
71
66
 
72
67
  This applies especially to message approvals. Never ask someone to approve a
73
- message they cannot see. In chat, show the subject and one fully filled sample
74
- message with no tokens first. Keep the tokenized template, good fill example,
75
- good omit example, bad fill example, why the bad fill is wrong, token notes, and
76
- fallback rules in `message-review.md` / `message-validation.md`.
68
+ message they cannot see. Show the subject, tokenized template, a filled sample
69
+ prospect version, good fill example, good omit example, bad fill example, why
70
+ the bad fill is wrong, token notes, your take, and suggested adjustment first.
71
+ The user should be able to compare "here is the template" against "here is what
72
+ one real prospect would receive" before approving, and understand exactly how
73
+ the tokens should and should not be filled.
77
74
 
78
75
  Every token needs a fallback. If the row does not have clean data for a token,
79
76
  the approval view should say whether to use a safe segment-level phrase, omit
@@ -95,17 +92,7 @@ Every customer-facing update should answer one of these:
95
92
  - What will the user see next?
96
93
  - What is protected until approval?
97
94
 
98
- Only promise parallel work when parallel work actually started. If the host
99
- cannot or should not launch background branches, say the real sequence:
100
- `I’ll tighten the filter first, then draft the message from the same sample.`
101
- Do not say `kicking off two workstreams`, `in parallel`, or `background` as
102
- aspirational copy.
103
-
104
- Before a brief approval, the user should see a slim approval brief in chat. The
105
- rich current brief exists in `brief.md`; the chat view is the decision surface,
106
- not the full working memo. `brief-v1.md` is an internal first-draft snapshot, not
107
- part of the normal approval UI. It should be skimmable in under 45 seconds and
108
- include:
95
+ Before a brief approval, the user should see:
109
96
 
110
97
  - who we are targeting
111
98
  - why they should care
@@ -116,11 +103,6 @@ include:
116
103
  - risks / assumptions
117
104
  - what happens after approval
118
105
 
119
- The offer / CTA should be useful before it is convenient. Avoid vague
120
- peer-call asks like "compare notes" unless the user explicitly chose that. The
121
- buyer should know what they get if they reply: a checklist, teardown, diagnostic,
122
- sample, benchmark, relevant example, or working session with a concrete output.
123
-
124
106
  For lead-source decisions, confidence comes from concrete counts. Do not say
125
107
  "strong sample", "73% match", or "meaningful concentration" without showing the
126
108
  sample size and what was counted. Prefer:
@@ -132,37 +114,6 @@ sampled engagers; 31 looked like real ICP fits, so I’d treat this as direction
132
114
  usable people if the remaining engagers behave similarly.
133
115
  ```
134
116
 
135
- Lead review chat should be short and numeric. It must use rendered Markdown,
136
- not a fenced code block, and include bullet-pointed provider/source-angle
137
- estimates, one bullet per angle, so the sourcing logic is easy to scan:
138
-
139
- ```text
140
- **1. Quick numbers**
141
- - **Signals / AI outbound posts:** 249 posts found. Sampled 40 engagers; 18/40
142
- looked usable. Estimate: 100-250 good warm fits.
143
- - **Sales Nav / active SaaS founders + GTM leaders:** 27,454 active profiles before
144
- filtering. First 25 had 12 strong/probable fits. Estimate: 300-800 good fits.
145
- - **Sales Nav / agencies + GTM consultants:** Smaller but higher intent. Estimate:
146
- 150-400 good fits.
147
- ```
148
-
149
- Then show chosen source, why it won, expected connection acceptance, expected
150
- reply rate, 3-5 sample leads, and one tradeoff. Full tables belong in
151
- `lead-review.md`.
152
-
153
- Lead filter chat should always use indexed rendered Markdown and show what
154
- changed: keep, exclude, why, expected impact, and
155
- `Open artifact: lead-filter.md`.
156
-
157
- Message review chat should use indexed rendered Markdown, show one fully filled
158
- sample message without tokens, and keep tokenized templates in the artifact.
159
-
160
- Final approval chat should use indexed rendered Markdown for a ready-to-create
161
- summary: campaign, target with concrete role/title names, lead source, filter,
162
- one filled sample message, what approval creates, and the safety note that
163
- nothing sends live until greenlight. Do not include sequence/settings in final
164
- approval; that belongs after campaign creation.
165
-
166
117
  Avoid:
167
118
 
168
119
  ```text
@@ -268,6 +219,27 @@ setting: `~/.codex/config.toml` with
268
219
 
269
220
  ## Approval Ethic
270
221
 
222
+ ## Parallelism + Naming
223
+
224
+ Source-angle comparison should be real, not implied. When the source is not
225
+ supplied and multiple source angles are viable, scout Signals, Sales Nav, and
226
+ relevant domain/contact paths as independent branches when the host can do so.
227
+ If the host runs them sequentially, keep the output numeric but do not claim the
228
+ source scout was parallel.
229
+
230
+ Only promise parallel post-lead work when parallel work actually started. If the
231
+ host cannot or should not launch background branches, say the real sequence:
232
+
233
+ ```text
234
+ I’ll tighten the filter first, then run message generation from the same sample.
235
+ ```
236
+
237
+ Do not say `kicking off two workstreams`, `in parallel`, or `background` as
238
+ aspirational copy.
239
+
240
+ Call the post-filter message stage `message generation` in chat.
241
+ `message-validation.md` is an internal proof artifact, not the workstream name.
242
+
271
243
  Be explicit about when nothing has been created yet:
272
244
 
273
245
  ```text
@@ -206,28 +206,27 @@
206
206
  "onEnter": [
207
207
  {
208
208
  "action": "show_brief_summary",
209
- "artifact": "brief.md"
209
+ "artifact": "brief-v1.md"
210
210
  },
211
211
  {
212
212
  "action": "render_brief_approval_checkpoint",
213
213
  "requiredVisibleContent": [
214
214
  "Campaign brief",
215
- "Target",
216
- "Core pain",
215
+ "Who we are targeting",
216
+ "Why they should care",
217
217
  "Offer / CTA",
218
- "Proof",
219
- "Lead plan",
218
+ "Proof to use",
219
+ "Lead source hypothesis",
220
220
  "Message angle",
221
- "Risks",
222
- "After approval",
221
+ "Risks / assumptions",
222
+ "What happens after approval",
223
223
  "approve this brief",
224
224
  "revise the brief",
225
225
  "then I will find good-fit leads"
226
226
  ],
227
- "minimumVisibleBriefDetail": "slim_approval_brief_before_question",
228
- "requiredArtifactLinks": ["brief.md"],
227
+ "minimumVisibleBriefDetail": "full_readable_brief_before_question",
228
+ "requiredArtifactLinks": ["brief-v1.md", "brief.md"],
229
229
  "artifactLinkTiming": "before_approval_question",
230
- "chatRenderRule": "Show the brief as rendered Markdown, never as a fenced code block. Use ## Campaign brief, a one-sentence bold Decision, indexed bold section labels, and short bullets. In Lead plan, translate provider shorthand into plain user-facing language about who will be searched for and why; do not rely on bare terms like signal discovery, RevOps, outbound systems, or pipeline architecture.",
231
230
  "avoidQuestionWhenOnlyUsefulAnswerIs": "looks good"
232
231
  },
233
232
  {
@@ -301,7 +300,8 @@
301
300
  {
302
301
  "action": "run_subskill",
303
302
  "target": "find-leads",
304
- "mode": "campaignless-preview"
303
+ "mode": "campaignless-preview",
304
+ "sourceScoutRule": "When source is not user-supplied and at least two viable source angles exist, scout independent source angles in parallel when host/tooling permits: Signals active-post branch, Sales Nav title/company branch, and Prospeo/domain branch only when relevant. If real parallel execution is unavailable, run the same scouts sequentially and do not claim parallel execution. Compare outputs by raw volume, n/N sampled fit, estimated good-fit range, expected reply range, and tradeoff."
305
305
  },
306
306
  {
307
307
  "action": "write_artifacts",
@@ -366,10 +366,10 @@
366
366
  "action": "show_lead_review",
367
367
  "artifact": "lead-review.md",
368
368
  "renderInlineSections": [
369
- "Lead source decision",
370
- "Chosen source",
369
+ "## Lead source decision",
370
+ "Recommendation",
371
371
  "Why it won",
372
- "Key numbers",
372
+ "Quick numbers",
373
373
  "Sample leads",
374
374
  "Tradeoff"
375
375
  ],
@@ -401,19 +401,21 @@
401
401
  "forbidPercentOnlyFitRates": true,
402
402
  "requiredArtifactLinks": ["lead-review.md"],
403
403
  "artifactLinkTiming": "before_next_step_or_revision_question",
404
- "chatRenderRule": "Show a slim rendered-Markdown decision summary only, never a fenced code block. Use indexed sections and short bullets: chosen source, why it won, bullet-pointed Quick numbers with one provider/source angle per bullet, raw volume, sampled fit rate as n/N, estimated good-fit range after cleanup, expected connection acceptance range, expected reply rate range, 3-5 representative sample leads, and one tradeoff. Keep evidence tables, selected posts, discarded paths, full sample rows, and lead-sample.json details in lead-review.md. Do not show plain filesystem paths unless links cannot be created."
404
+ "doNotCompressToSummaryOnly": false,
405
+ "doNotRenderArtifactLinksOnly": true,
406
+ "chatRenderRule": "Show a slim rendered-Markdown decision summary only, never a fenced code block. Use indexed sections and short bullets: recommendation, why it won, Quick numbers with one provider/source angle per bullet, raw volume, sampled fit rate as n/N, estimated good-fit range after cleanup, expected reply rate range, 3-5 representative sample leads, and one tradeoff. Keep evidence tables, selected posts, discarded paths, full sample rows, and lead-sample.json details in lead-review.md. Do not show plain filesystem paths unless links cannot be created."
405
407
  },
406
408
  {
407
409
  "action": "render_post_lead_parallel_progress",
408
410
  "requiredVisibleContent": [
409
411
  "Lead source is set",
410
412
  "Tighten the fit filter",
411
- "Draft the first message",
413
+ "Message generation",
412
414
  "approved brief and real sample leads",
413
415
  "parallel only if real parallel branches were launched"
414
416
  ],
415
417
  "timeEstimate": "~2-3 min",
416
- "chatRenderRule": "If real parallel workers/branches were actually launched, say: 'I’m kicking off two workstreams now' and list the two branches. If not, do not mention parallel/background work; say: 'I’ll tighten the filter first, then draft the first message from the same approved brief and sample leads.' Never claim parallelism unless the host actually started parallel execution."
418
+ "chatRenderRule": "If real parallel workers/branches were actually launched, say: 'I’m kicking off two workstreams now' and list 'Tighten the fit filter' and 'Message generation'. If not, do not mention parallel/background work; say: 'I’ll tighten the filter first, then run message generation from the same approved brief and sample leads.' Never claim parallelism unless the host actually started parallel execution. User-facing stage name is message generation; message-validation.md is only the internal artifact."
417
419
  },
418
420
  {
419
421
  "action": "ask_continue_revise_or_confirm_only_if_needed",
@@ -476,7 +478,7 @@
476
478
  "action": "show_lead_filter_summary",
477
479
  "artifact": "lead-filter.md",
478
480
  "renderInlineSections": [
479
- "Lead filter",
481
+ "## Lead filter",
480
482
  "Keep",
481
483
  "Exclude",
482
484
  "Why",
@@ -623,7 +625,7 @@
623
625
  "recommendation"
624
626
  ],
625
627
  "mustRenderInlineBeforeQuestion": true,
626
- "minimumVisibleMessageDetail": "filled_sample_message_no_tokens",
628
+ "minimumVisibleMessageDetail": "filled_sample_message_only",
627
629
  "requiredArtifactLinks": ["message-review.md"],
628
630
  "artifactLinkTiming": "before_approval_question",
629
631
  "requiredFileLabels": [
@@ -685,9 +687,11 @@
685
687
  "questionPrerequisiteVisibleLabels": [
686
688
  "Status: message-review",
687
689
  "Subject:",
690
+ "Tokenized template:",
688
691
  "Sample prospect fill:",
692
+ "Token fill basis:",
689
693
  "My take:",
690
- "Concern:",
694
+ "Suggested adjustment:",
691
695
  "Recommendation:"
692
696
  ],
693
697
  "forbiddenWhenMissingVisibleMessage": true,
@@ -59,8 +59,6 @@ lead-filter.md
59
59
  message-prep.md (optional)
60
60
  message-candidate-drafts.md (optional, generated from find-leads basis rows)
61
61
  message-validation.md
62
- message-review.md
63
- message-review-decision.md
64
62
  approval-packet.md
65
63
  commit-gate-decision.md
66
64
  ```
@@ -121,33 +121,29 @@ rerun `$sellable:create-campaign`. A normal chat question is acceptable only for
121
121
  non-interactive `codex exec` smoke/rehearsal runs because structured user input
122
122
  is unavailable by design there.
123
123
 
124
- The packet should read like an AI GTM engineer asking for one final creation
125
- decision, not an internal validation report. Chat should show a slim approval
126
- surface only:
127
-
128
- 1. **campaign** company + sender
129
- 2. **target** — concise ICP summary from `brief.md`, including concrete
130
- role/title names so the user can verify we are aiming at the right buyers
131
- 3. **lead source** — selected source plus one key metric from `lead-review.md`
132
- (for example `17/25 sampled fits`, `520 active profiles`, or estimated usable
133
- leads). Put the full evidence table in `lead-review.md`, not chat.
134
- 4. **filter** — one-line keep/exclude summary from `lead-filter.md`
135
- 5. **sample message** one fully filled sample message with no `{{tokens}}`
136
- 6. **what approval creates** — campaign draft + review batch preparation, not
137
- live sending
138
-
139
- Do not include sequence/settings in the pre-mint final approval packet. Sequence
140
- attachment and launch settings happen after campaign creation and before the
141
- later greenlight.
142
-
143
- Keep implementation details, tokenized templates, lead tables, rubric JSON, and
144
- validation notes available in `approval-packet.md` and the supporting artifacts.
145
- Do not show raw filesystem paths unless links cannot be created or the user asks.
146
- Use one normal chat link: `Open artifact: approval-packet.md`.
147
-
148
- The packet artifact must include a dedicated `## Message Review` section
149
- immediately before `## Approved Message Template`. This is the customer-facing
150
- messaging gate. It should not be a raw validation dump; it should answer:
124
+ The packet should read like an AI GTM engineer explaining the campaign, not an
125
+ internal validation report. Start with the practical direction in plain
126
+ language: who we will contact, why this buyer should care, what lead source we
127
+ will use, what the first message says, and what happens if the user approves.
128
+ Keep implementation details available, but move them below the customer-facing
129
+ summary.
130
+
131
+ 1. **brief** — `brief.md` thesis, product, ICP, offer
132
+ 2. **lead sample** first 5-10 rows from `lead-sample.json` rendered as
133
+ `Name / Title / Company` lines, plus the `lead-review.md` pass-rate
134
+ and supplied-source framing when `lead-source-intake.json` exists:
135
+ supplied people list, existing Sellable lead list, or supplied account list
136
+ plus people search
137
+ 3. **lead filter** — the `Decision`, `Who We'll Keep`, `Who We'll Exclude`,
138
+ `Pass Rate`, and `Recommendation` blocks from `lead-filter.md`; keep
139
+ rubric internals in `Implementation Details` unless the user asks to inspect
140
+ the saved filter criteria
141
+ 4. **message validation** — the `Selected Winner` from `message-validation.md`,
142
+ rendered as it will appear in the outbound, plus the `Findings` + `Recommendation`
143
+
144
+ The packet must include a dedicated `## Message Review` section immediately
145
+ before `## Approved Message Template`. This is the customer-facing messaging
146
+ gate. It should not be a raw validation dump; it should answer:
151
147
 
152
148
  - `Verdict:` strong / usable-but-could-improve / needs-revision
153
149
  - `What works:` why the message is likely to earn replies
@@ -167,10 +163,6 @@ message from the brief. If no winner/template can be extracted, this exact-match
167
163
  gate is skipped, but the packet still needs a usable approved template unless
168
164
  the user explicitly chose AI-generated messages.
169
165
 
170
- The chat render must not lead with `## Approved Message Template` or token fill
171
- rules. Show one filled sample first. The artifact can contain the tokenized
172
- template and fill basis.
173
-
174
166
  Do NOT render the packet as a bundle of opaque validation anchors or a dump
175
167
  of raw JSON. The user is approving a live campaign — they need to see what
176
168
  they are approving.
@@ -131,20 +131,6 @@ usable leads after filtering, likely connection acceptance range, likely reply
131
131
  range, and estimate basis. If exact performance data is unavailable, use a
132
132
  directional range and label it `directional`, not definitive.
133
133
 
134
- `## Evidence Snapshot` and the visible lead-review chat must break estimates out
135
- by provider/source angle. Do not collapse everything into one raw count. Use
136
- one row or bullet per angle. The visible chat version should be rendered
137
- Markdown with indexed sections and short bullets, not a fenced code block. For
138
- example:
139
-
140
- - `Signals / AI outbound posts`
141
- - `Sales Nav / active SaaS founders + GTM leaders`
142
- - `Sales Nav / agencies + GTM consultants`
143
- - `Prospeo / domain-filtered agencies`
144
-
145
- Each angle must show raw pool, sampled fits as `n/N`, estimated good-fit range
146
- after cleanup, expected reply-rate range, and confidence basis.
147
-
148
134
  `lead-sample.json` must include enough structured lead data for downstream
149
135
  filtering:
150
136
 
@@ -40,7 +40,7 @@ must contain:
40
40
  - a plain confirmation that the campaign was created and the approved brief was
41
41
  saved
42
42
  - a one-line orientation sentence: `Open this to watch lead sourcing, rubric
43
- scoring, and messaging populate live.`
43
+ scoring, and messaging populate live.`
44
44
  - the `watchUrl` captured from the `create_campaign` response
45
45
 
46
46
  Example skeleton:
@@ -293,6 +293,13 @@ Use first when LinkedIn activity plus tighter role / company filters matter.
293
293
  - When you fall back from the recently-posted slice, say clearly that the posted filter was tested, explain why it was dropped, and keep the best non-posted lane as the source of truth.
294
294
  - Use `RECENTLY_CHANGED_JOBS` when job-change activity is part of the targeting thesis.
295
295
  - If quality is poor, tighten the lane with role, industry, seniority, geography, or activity filters.
296
+ - After each Sales Nav preview, sanity-check the result before using it in the
297
+ decision: the returned `searchUrl` should include filters, the first page
298
+ should visibly match the intended roles and companies, and the count should
299
+ be plausible. If filters did not apply, the search errors, or the total looks
300
+ obviously unfiltered, retry once with clean filter objects. If it still fails,
301
+ mark Sales Nav as a provider/tool issue and do not include it as a winning
302
+ source.
296
303
  - If quality is good but scale is too small, widen the lane by adding/removing roles, expanding industries, widening headcount bands, or relaxing activity constraints.
297
304
  - Use as many smart refinement steps as needed within the remaining probe budget instead of returning the first under-scaled recipe.
298
305
  - If the lane is meant to support scalable outbound, do not stop at a merely borderline workable result when obvious expansion steps remain.
@@ -114,6 +114,7 @@ NEVER do these:
114
114
 
115
115
  <filter_format>
116
116
  ALL filter values MUST include id, text, and selectionType.
117
+ Pass `filters` as an array of objects. Do not stringify filters as JSON.
117
118
 
118
119
  CORRECT:
119
120
 
@@ -145,6 +146,21 @@ WRONG:
145
146
 
146
147
  </filter_format>
147
148
 
149
+ <result_validation>
150
+ After every `search_sales_nav` call, sanity-check the returned result before
151
+ using it in a source decision:
152
+
153
+ - `searchUrl` should include a `filters:List(...)` query, not only `keywords`.
154
+ - The sample rows should visibly match the intended role/company lane.
155
+ - The total result count should be plausible for the filters used.
156
+
157
+ If filters did not apply, the search errors, or the result count is obviously
158
+ unfiltered, do not present Sales Nav as a valid lane. Retry once with clean
159
+ filter objects if the issue was formatting. If it still fails, say plainly:
160
+ "Sales Nav did not apply the filters cleanly, so I’m not using it for this
161
+ decision." Then continue with Signals or Prospeo if they have usable evidence.
162
+ </result_validation>
163
+
148
164
  <static_filters>
149
165
  These filters need NO lookup - use these IDs directly:
150
166