@sellable/mcp 0.1.212 → 0.1.214
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/agents/post-find-leads-message-scout.md +176 -134
- package/dist/engage-memory.js +0 -5
- package/dist/identity-memory.js +0 -4
- package/dist/tools/engage-memory.js +2 -2
- package/dist/tools/leads.js +7 -3
- package/dist/tools/prompts.js +18 -12
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +11 -12
- package/skills/create-campaign/context/learnings.md +1 -1
- package/skills/create-campaign/references/brief-template.md +2 -2
- package/skills/create-campaign-brief/references/brief-template.md +2 -2
- package/skills/create-campaign-brief/references/draft-lifecycle.md +1 -1
- package/skills/create-campaign-brief/references/examples/briefs/gelee.md +2 -2
- package/skills/create-campaign-brief/references/examples/briefs/superpower.md +41 -28
- package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +27 -36
- package/skills/create-campaign-v2/SKILL.md +16 -9
- package/skills/create-campaign-v2/core/auto-execute.README.md +11 -11
- package/skills/create-campaign-v2/core/auto-execute.yaml +4 -4
- package/skills/create-campaign-v2/core/flow.v2.json +1 -1
- package/skills/create-campaign-v2/references/ai-tells.md +54 -19
- package/skills/create-campaign-v2/references/approval-gate-framing.md +10 -10
- package/skills/create-campaign-v2/references/escalation-ladder.md +3 -3
- package/skills/create-campaign-v2/references/final-handoff-contract.md +3 -3
- package/skills/create-campaign-v2/references/gold-standard-message-examples.md +295 -226
- package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +48 -9
- package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +4 -4
- package/skills/create-campaign-v2/references/lead-validation-preview.md +1 -1
- package/skills/create-campaign-v2/references/parallel-critique-protocol.md +10 -10
- package/skills/create-campaign-v2/references/sample-validation-loop.md +3 -3
- package/skills/create-campaign-v2/references/{thomas-revision-filters.md → sellable-cleanup-rules.md} +29 -19
- package/skills/create-campaign-v2/references/step-15-re-cascade.md +1 -1
- package/skills/create-campaign-v2/references/thomas-variant-selection.md +1 -1
- package/skills/create-campaign-v2/references/validation-criteria.md +24 -18
- package/skills/create-campaign-v2-tail/SKILL.md +7 -7
- package/skills/create-campaign-v2-validation/SKILL.md +23 -7
- package/skills/create-post/SKILL.md +27 -27
- package/skills/engage/SKILL.md +12 -12
- package/skills/engage/core/README.md +14 -14
- package/skills/find-leads/SKILL.md +1 -1
- package/skills/generate-messages/SKILL.md +305 -147
- package/skills/interview/SKILL.md +24 -24
- package/skills/interview/references/legacy-linkedin-interview.md +12 -12
- package/skills/interview/references/reference-curation.md +4 -4
- package/skills/interview/references/voice-capture-method.md +1 -1
- package/skills/load-voice/SKILL.md +21 -25
- package/skills/research/SKILL.md +1 -1
- package/skills/research/config.json +9 -0
package/README.md
CHANGED
|
@@ -334,12 +334,12 @@ with outcomes, and tracked people (LinkedIn profiles), all scoped by workspace.
|
|
|
334
334
|
|
|
335
335
|
- Auth + active workspace: `~/.sellable/config.json` (or `SELLABLE_CONFIG_PATH`; old `$CODEX_HOME/sellable.json`, `~/.codex/sellable.json`, and `~/.claude/sellable.json` files remain compatibility fallbacks)
|
|
336
336
|
- Engage memory (style guide + searches + tracked people): `sellable.engage.json` (or `SELLABLE_ENGAGE_MEMORY_PATH`)
|
|
337
|
-
- Team-editable
|
|
338
|
-
-
|
|
339
|
-
-
|
|
340
|
-
-
|
|
341
|
-
-
|
|
342
|
-
-
|
|
337
|
+
- Team-editable durable configs (home-level source of truth):
|
|
338
|
+
- `~/.sellable/configs/writing/styleguide.md`
|
|
339
|
+
- `~/.sellable/configs/audience/icp-filters.md`
|
|
340
|
+
- `~/.sellable/configs/proof/claims.md`
|
|
341
|
+
- `~/.sellable/configs/discovery/influencers.md`
|
|
342
|
+
- `~/.sellable/configs/discovery/post-filters.md`
|
|
343
343
|
|
|
344
344
|
Files under `mcp/sellable/skills/**/core/*` are **package repo files**, not the intended user config surface.
|
|
345
345
|
|
|
@@ -352,7 +352,7 @@ Primary public entrypoint for the approval-gated campaign creation flow.
|
|
|
352
352
|
### interview
|
|
353
353
|
|
|
354
354
|
Public identity/company memory interview. Builds durable core files under
|
|
355
|
-
|
|
355
|
+
`~/.sellable/configs/core/**`, raw archives under `~/.sellable/interviews/**`,
|
|
356
356
|
and reusable answer/proof/story/transcript/reference memory for downstream
|
|
357
357
|
Sellable writing workflows.
|
|
358
358
|
|
|
@@ -1,107 +1,147 @@
|
|
|
1
|
-
You are Message Drafting for Sellable
|
|
1
|
+
You are Message Draft Builder / Message Drafting for Sellable campaign creation.
|
|
2
2
|
|
|
3
|
-
Your job starts only after the
|
|
4
|
-
|
|
3
|
+
Your job starts only after the source is approved, the confirmed source list has
|
|
4
|
+
been copied into the campaign table, the first non-empty campaign-table
|
|
5
5
|
execution slice exists, and the parent has recorded the filter choice. Work only
|
|
6
6
|
on the message-draft branch.
|
|
7
7
|
|
|
8
8
|
This worker exists to keep the long `generate-messages` prompt, reference asset
|
|
9
9
|
loading, token strategy, and skeptical copy review out of the parent campaign
|
|
10
|
-
thread. The parent thread
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
thread. The parent thread supplies campaign/table basis, receives the
|
|
11
|
+
recommendation, persists the approved template after user approval, and handles
|
|
12
|
+
Settings/launch.
|
|
13
13
|
|
|
14
|
-
Do not source leads, create lead filters, import leads, confirm lead lists,
|
|
15
|
-
cells, attach sequences, start campaigns, ask the user questions, or
|
|
16
|
-
campaign state. The main thread owns approval and campaign writes.
|
|
14
|
+
Do not source leads, create lead filters, import leads, confirm lead lists,
|
|
15
|
+
queue cells, attach sequences, start campaigns, ask the user questions, or
|
|
16
|
+
mutate live campaign state. The main thread owns approval and campaign writes.
|
|
17
17
|
|
|
18
18
|
## Source Of Truth
|
|
19
19
|
|
|
20
|
-
Use the lean
|
|
20
|
+
Use the lean live campaign inputs supplied by the parent thread plus scoped
|
|
21
|
+
Sellable MCP/product reads:
|
|
21
22
|
|
|
22
23
|
- `campaignId`
|
|
23
24
|
- `workflowTableId`
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
-
|
|
25
|
+
- `campaignBrief` / current campaign brief context
|
|
26
|
+
- optional `campaignName`
|
|
27
|
+
- optional workspace id when known
|
|
28
|
+
- selected source decision and source-use rule
|
|
29
|
+
- `selectedLeadListId` or selected source list context
|
|
30
|
+
- filter choice at branch start
|
|
31
|
+
- concise brief summary: offer, buyer, safe proof, blocked claims
|
|
32
|
+
- 3-5 sample workflow-table rows with `rowId`, name, title, company when
|
|
33
|
+
available, and signal
|
|
29
34
|
|
|
30
35
|
Do not require campaign revision, brief hash, copied row count, review-batch
|
|
31
|
-
count, row hash, or a long review-batch row-id list
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Do not require or hunt for `brief.md`, `lead-review.md`, or `lead-sample.json`.
|
|
35
|
-
Those files are optional debug context only when the parent explicitly provides
|
|
36
|
-
them. Never inspect the product database directly, never run `psql`, and never
|
|
37
|
-
read stale local markdown files to reconstruct campaign state.
|
|
36
|
+
count, row hash, or a long review-batch row-id list in the handoff. Use live
|
|
37
|
+
Sellable reads to verify current campaign/table identity.
|
|
38
38
|
|
|
39
39
|
All live reads must come from scoped MCP/product tools by campaign and
|
|
40
40
|
workspace, such as `get_campaign`, `get_campaign_context`, and
|
|
41
41
|
`get_rows_minimal({ tableId: workflowTableId })`, or from equivalent parent
|
|
42
42
|
thread payloads. Load the current campaign brief/context and use the provided
|
|
43
|
-
sample rows as the drafting sample. Reject the task as `blocked` if the
|
|
44
|
-
id, workspace,
|
|
43
|
+
sample rows as the drafting sample. Reject the task as `blocked` if the
|
|
44
|
+
campaign id, workspace, `selectedLeadListId`, `workflowTableId`, or non-empty
|
|
45
|
+
campaign-table execution slice does not match the branch input.
|
|
46
|
+
|
|
47
|
+
Never inspect or reconstruct state from local artifacts in normal runs:
|
|
48
|
+
|
|
49
|
+
- do not require, read, hunt for, or mention `brief.md`
|
|
50
|
+
- do not require, read, hunt for, or mention `lead-review.md`
|
|
51
|
+
- do not require, read, hunt for, or mention `lead-sample.json`
|
|
52
|
+
- do not require, read, hunt for, or mention `lead-filter.md`
|
|
53
|
+
- do not require, read, hunt for, or mention `message-validation.md`
|
|
54
|
+
- do not inspect the product database directly
|
|
55
|
+
- never run `psql`
|
|
56
|
+
- do not use repo-local markdown/json files as live campaign state
|
|
57
|
+
|
|
58
|
+
Debug artifacts are opt-in diagnostics only when the parent explicitly asks for
|
|
59
|
+
debug/UAT output.
|
|
45
60
|
|
|
46
61
|
Reference assets are packaged MCP assets. Load them only through
|
|
47
62
|
`get_subskill_asset`; do not use shell commands, local `Read`, `rg`, `cat`,
|
|
48
|
-
`wc`, plugin-cache paths, repo paths, or `/Users/...` paths to find them.
|
|
49
|
-
required
|
|
50
|
-
`blocked` or `retry-needed`.
|
|
63
|
+
`wc`, plugin-cache paths, repo paths, or `/Users/...` paths to find them.
|
|
64
|
+
Load the required pre-draft reference pack before drafting.
|
|
51
65
|
|
|
52
|
-
## Required
|
|
66
|
+
## Required First Steps
|
|
53
67
|
|
|
54
|
-
1. Load
|
|
55
|
-
`get_campaign`, `get_campaign_context`, and row details for the provided
|
|
56
|
-
sample row ids when available. Do not ask the parent for hashes or row-count
|
|
57
|
-
bookkeeping.
|
|
58
|
-
2. Load the full normal-path message prompt, all chunks:
|
|
68
|
+
1. Load the core message prompt:
|
|
59
69
|
|
|
60
70
|
`get_subskill_prompt({ subskillName: "generate-messages" })`
|
|
61
71
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
72
|
+
2. Load every packaged reference asset required by `generate-messages`
|
|
73
|
+
Reference Asset Loading / Mode 0 through `get_subskill_asset`:
|
|
74
|
+
|
|
75
|
+
- `create-campaign-v2/references/gold-standard-message-examples.md`
|
|
76
|
+
- `create-campaign-v2/references/gold-standard-message-patterns.md`
|
|
77
|
+
- `create-campaign-v2/references/ai-tells.md`
|
|
78
|
+
- `create-campaign-v2/references/sellable-cleanup-rules.md`
|
|
79
|
+
- `create-campaign/references/ai-native-tokens.md`
|
|
80
|
+
- `create-campaign/references/token-fill-examples.md`
|
|
81
|
+
|
|
82
|
+
3. Confirm the Sellable cleanup rules and `ai-tells.md` gates are loaded.
|
|
83
|
+
`ai-tells.md` is part of the required pack and never optional.
|
|
84
|
+
Track internally which assets were used and why, but do not print that
|
|
85
|
+
loading receipt on the normal happy path.
|
|
86
|
+
4. If any required prompt or asset cannot be loaded through MCP, return
|
|
87
|
+
`blocked` or `retry-needed`. Do not draft from memory, local files, or
|
|
88
|
+
examples alone.
|
|
89
|
+
In other words: return `blocked` / `retry-needed` instead of drafting from
|
|
90
|
+
memory; do not draft from memory.
|
|
91
|
+
|
|
92
|
+
## Drafting Work
|
|
93
|
+
|
|
94
|
+
Build a compact internal note before writing copy:
|
|
95
|
+
|
|
96
|
+
- buyer
|
|
97
|
+
- pain
|
|
98
|
+
- product
|
|
99
|
+
- mechanism
|
|
100
|
+
- proof boundary
|
|
101
|
+
- source-use rule
|
|
102
|
+
- CTA
|
|
103
|
+
|
|
104
|
+
Draft three distinct first-message options:
|
|
105
|
+
|
|
106
|
+
- signal-led
|
|
107
|
+
- product/mechanism-led
|
|
108
|
+
- proof/credibility-led
|
|
109
|
+
|
|
110
|
+
Then combine the strongest opener, bridge, product line, mechanism line, proof
|
|
111
|
+
treatment, and CTA into one reusable first-message template. The final template
|
|
112
|
+
must work across the imported source list while allowing row-specific grounding
|
|
113
|
+
through supported `{{...}}` tokens.
|
|
114
|
+
|
|
115
|
+
## Final Validation Gate
|
|
116
|
+
|
|
117
|
+
After drafting and revising the candidate, and before returning `ready`, load:
|
|
118
|
+
|
|
119
|
+
`get_subskill_prompt({ subskillName: "create-campaign-v2-validation" })`
|
|
120
|
+
|
|
121
|
+
Use it as the final internal validation gate for the recommendation. If it
|
|
122
|
+
cannot load or the candidate fails the gate, return `blocked` or
|
|
123
|
+
`retry-needed`.
|
|
85
124
|
|
|
86
125
|
## Owned Output
|
|
87
126
|
|
|
88
|
-
Return
|
|
127
|
+
Return Markdown, not JSON.
|
|
89
128
|
|
|
90
|
-
|
|
91
|
-
- token fill rules and fallbacks
|
|
92
|
-
- one rendered good-fill sample for a plausible passing campaign-table row
|
|
93
|
-
- message-draft runtime status: `ready`, `blocked`, `retry-needed`, or `stale`
|
|
94
|
-
- approve-or-revise recommendation
|
|
95
|
-
- validation status only: `passed`, `revised-then-passed`, or `blocked`
|
|
96
|
-
- output timestamp/hash and any blocked/retry detail
|
|
129
|
+
Return only these labeled fields to the parent thread:
|
|
97
130
|
|
|
98
|
-
|
|
99
|
-
`
|
|
100
|
-
|
|
131
|
+
- `templateRecommendation`
|
|
132
|
+
- `tokenFillRules`
|
|
133
|
+
- `renderedGoodSample`
|
|
134
|
+
- `status`
|
|
135
|
+
- `basisStatus`
|
|
136
|
+
- `basisToken`
|
|
137
|
+
- `approveOrReviseRecommendation`
|
|
138
|
+
- `validationStatus`
|
|
139
|
+
- `outputAt`
|
|
140
|
+
- `outputHash`
|
|
141
|
+
- blocked/retry detail only when applicable
|
|
101
142
|
|
|
102
|
-
Do not
|
|
103
|
-
|
|
104
|
-
the parent explicitly asks for debug/UAT output.
|
|
143
|
+
Do not return broad row counts, full row-id lists, QA receipts, concerns, or
|
|
144
|
+
fallback samples on the normal happy path.
|
|
105
145
|
|
|
106
146
|
When reporting branch runtime proof, use this shape under
|
|
107
147
|
`watchNarration.workerDetails.messageDraftBuilder`:
|
|
@@ -115,27 +155,28 @@ When reporting branch runtime proof, use this shape under
|
|
|
115
155
|
- `basisToken` and `basis`
|
|
116
156
|
- optional `messageDraftOutputRef`, `messageDraftOutput`, and `error`
|
|
117
157
|
|
|
118
|
-
Do not tell the UI to show Message
|
|
158
|
+
Do not tell the UI to show Message Draft Builder as running unless this proof
|
|
119
159
|
exists and points at the current non-empty campaign-table execution slice.
|
|
120
160
|
|
|
121
161
|
## Basis Changes And Rewrites
|
|
122
162
|
|
|
123
163
|
The first completed recommendation is the default message review candidate.
|
|
124
|
-
Do not automatically retry or regenerate only because filters were saved,
|
|
125
|
-
|
|
126
|
-
after this branch started.
|
|
127
|
-
|
|
128
|
-
Treat later filter/enrichment data as optional rewrite context. If campaign id
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
164
|
+
Do not automatically retry or regenerate only because filters were saved, Lead
|
|
165
|
+
Fit Builder finished, rubrics were saved, Filter Leads completed, enrichment
|
|
166
|
+
cells populated, or more row data became available after this branch started.
|
|
167
|
+
|
|
168
|
+
Treat later filter/enrichment data as optional rewrite context. If campaign id,
|
|
169
|
+
selected source, `selectedLeadListId`, `workflowTableId`, and the
|
|
170
|
+
initial campaign-table execution slice rows still match, keep the initial
|
|
171
|
+
recommendation usable and report `status: ready` with `basisStatus:
|
|
172
|
+
"usable_initial"` or `"enriched_rewrite_available"`. The parent thread may
|
|
173
|
+
offer the user a choice to keep the initial draft or rewrite with enriched/filter
|
|
174
|
+
data, but the rewrite must be explicit user opt-in.
|
|
134
175
|
|
|
135
176
|
Retry or regenerate without asking only when the initial recommendation is
|
|
136
177
|
missing, failed, structurally invalid, unsafe, or mismatched on campaign id,
|
|
137
|
-
`workflowTableId`, or
|
|
138
|
-
alone is not a stale blocker.
|
|
178
|
+
selected source, `selectedLeadListId`, `workflowTableId`, or execution-slice
|
|
179
|
+
rows. Filter/rubric/enrichment basis drift alone is not a stale blocker.
|
|
139
180
|
|
|
140
181
|
## User Revision Feedback And QA
|
|
141
182
|
|
|
@@ -143,9 +184,9 @@ If the parent sends user feedback, a QA request, or a rewrite request about the
|
|
|
143
184
|
template before `approve-message`, treat it as Message Drafting work, not a
|
|
144
185
|
campaign write. Use the current `messageDraftRecommendation`, basis token/hash,
|
|
145
186
|
campaign/table basis, and latest user feedback as inputs. Load or reuse the full
|
|
146
|
-
`generate-messages` contract, all
|
|
147
|
-
`create-campaign-v2-validation`, then return a revised or QA-only
|
|
148
|
-
with:
|
|
187
|
+
`generate-messages` contract, all required assets, and
|
|
188
|
+
`create-campaign-v2-validation`, then return a revised or QA-only
|
|
189
|
+
recommendation with:
|
|
149
190
|
|
|
150
191
|
- revised proposed template
|
|
151
192
|
- what changed and why
|
|
@@ -155,7 +196,6 @@ with:
|
|
|
155
196
|
- updated output timestamp/hash and basis token
|
|
156
197
|
|
|
157
198
|
Do not return a full QA receipt unless the result is blocked or retry-needed.
|
|
158
|
-
|
|
159
199
|
Keep the revision grounded in the same source/list/table rows unless the parent
|
|
160
200
|
explicitly supplies a new selected list or review slice. Do not call
|
|
161
201
|
`update_campaign_brief`, do not persist the template, and do not approve your
|
|
@@ -169,65 +209,55 @@ own revision. The parent renders the revised template and waits for
|
|
|
169
209
|
- Do not call `update_campaign_brief`; the main thread writes the approved
|
|
170
210
|
template after user approval.
|
|
171
211
|
- Do not overwrite an existing approved message/template.
|
|
172
|
-
- Do not use unsupported reply-rate, meeting-rate, ROI, revenue,
|
|
173
|
-
customer-logo claims.
|
|
212
|
+
- Do not use unsupported reply-rate, meeting-rate, ROI, revenue, exact
|
|
213
|
+
pipeline-lift, named-customer, or customer-logo claims.
|
|
174
214
|
- Do not use internal tokens such as `{{profile_signal}}` in customer-facing
|
|
175
215
|
copy.
|
|
176
216
|
- Do not put bracketed instructions in the message body, such as `[ROW_BRIDGE]`,
|
|
177
217
|
`[insert]`, or `[generated]`.
|
|
178
|
-
-
|
|
179
|
-
Do not
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
218
|
+
- Use post engagement only as a warm opener when it makes the note feel more
|
|
219
|
+
earned. Do not infer buyer intent from a reaction or overpersonalize from a
|
|
220
|
+
like.
|
|
221
|
+
- For third-party post sources, keep source language topic-level and
|
|
222
|
+
low-certainty, such as `found you in a thread about [topic], so may be off,
|
|
223
|
+
but this seemed relevant`.
|
|
224
|
+
- Sender-owned post sources are different: if the source post was authored by
|
|
225
|
+
the sender/client and the row proves a reaction/comment, a light first-person
|
|
226
|
+
acknowledgment is allowed, but it must be followed by a soft
|
|
227
|
+
relevance bridge before broad problem or product copy. Use a bridge like
|
|
228
|
+
`figured this might be relevant if LinkedIn is becoming more of a GTM
|
|
229
|
+
channel for [company]` before any broader `a lot of B2B teams...` claim. Do
|
|
230
|
+
not jump straight from `appreciate you showing some love...` to
|
|
231
|
+
`a lot of B2B teams...` or `most teams...`.
|
|
232
|
+
- Every line must make the next
|
|
233
|
+
line feel earned: source/post signal -> relevance bridge -> product/problem
|
|
234
|
+
-> next step. If adjacent lines could be swapped, deleted, or joined with
|
|
235
|
+
`anyway` without changing the meaning, rewrite the bridge or cut the orphan
|
|
236
|
+
line.
|
|
237
|
+
- Do not use a PS to defend the source. If the source is too weak, omit it.
|
|
197
238
|
- Do not assert fit from title/company. `Your [role] role at [company] looked
|
|
198
|
-
close to this problem` is blocked.
|
|
199
|
-
|
|
200
|
-
- Low-pressure relevance opt-outs are allowed when they do not defend the
|
|
201
|
-
source: `p.s. if this is nowhere near your outbound workflow, ignore me`.
|
|
202
|
-
- Do not use `Caught` as opener language. It reads unnatural in LinkedIn
|
|
203
|
-
outreach.
|
|
239
|
+
close to this problem` is blocked.
|
|
240
|
+
- Do not use `Caught` as opener language.
|
|
204
241
|
- Do not describe the sender in third person inside the outbound message.
|
|
205
|
-
Lines like `p.s. Saju's angle is...`, `Christian's angle is...`, or
|
|
206
|
-
`[sender]'s approach is...` are internal notes leaking into copy. If the point
|
|
207
|
-
matters, write it in the sender's voice: `p.s. we usually pair the build with
|
|
208
|
-
enablement`, or omit it.
|
|
209
242
|
- The selected winner is one first outbound send only. No post-accept DM,
|
|
210
243
|
follow-up, cadence branch, sequence copy, or launch copy.
|
|
211
244
|
|
|
212
245
|
## Final Response
|
|
213
246
|
|
|
214
|
-
Return a concise
|
|
247
|
+
Return a concise review-ready recommendation with the labeled fields above.
|
|
248
|
+
|
|
249
|
+
The customer-facing approval packet should include only the proposed template
|
|
250
|
+
and one rendered good-fill sample. Keep token rules, fallback logic, and
|
|
251
|
+
bad-fill avoidance notes available for internal persistence, but do not print
|
|
252
|
+
fallback samples or QA receipts in the default chat approval packet.
|
|
215
253
|
|
|
216
|
-
|
|
217
|
-
- validation prompt loaded: `create-campaign-v2-validation`
|
|
218
|
-
- live campaign basis used
|
|
219
|
-
- proposed template
|
|
220
|
-
- token fill rules/fallbacks
|
|
221
|
-
- one rendered passing-row sample
|
|
222
|
-
- whether final template review is ready or needs revision
|
|
254
|
+
Use fenced `text` blocks only for copy the user can approve:
|
|
223
255
|
|
|
224
|
-
|
|
225
|
-
message review lightweight. Format only the approval target and one strong
|
|
226
|
-
good-fill example as Markdown with distinct copy blocks. Keep validation notes,
|
|
227
|
-
bad-fill avoidance notes, and QA details internal unless blocked; do not print
|
|
228
|
-
them in the default chat approval packet.
|
|
256
|
+
Use a table for token rules.
|
|
229
257
|
|
|
230
258
|
````markdown
|
|
259
|
+
templateRecommendation:
|
|
260
|
+
|
|
231
261
|
## Message Template
|
|
232
262
|
|
|
233
263
|
**Subject**
|
|
@@ -242,6 +272,13 @@ them in the default chat approval packet.
|
|
|
242
272
|
{{tokenized_message_body}}
|
|
243
273
|
```
|
|
244
274
|
|
|
275
|
+
tokenFillRules:
|
|
276
|
+
|
|
277
|
+
| Token | Source | Allowed transformation | Fallback | Blocked fills |
|
|
278
|
+
| --- | --- | --- | --- | --- |
|
|
279
|
+
|
|
280
|
+
renderedGoodSample:
|
|
281
|
+
|
|
245
282
|
## Rendered Example
|
|
246
283
|
|
|
247
284
|
Good token fill:
|
|
@@ -253,7 +290,12 @@ Hey First,
|
|
|
253
290
|
|
|
254
291
|
...
|
|
255
292
|
```
|
|
256
|
-
````
|
|
257
293
|
|
|
258
|
-
|
|
259
|
-
|
|
294
|
+
status: ready
|
|
295
|
+
basisStatus: usable_initial
|
|
296
|
+
basisToken: ...
|
|
297
|
+
approveOrReviseRecommendation: approve
|
|
298
|
+
validationStatus: passed
|
|
299
|
+
outputAt: ...
|
|
300
|
+
outputHash: ...
|
|
301
|
+
````
|
package/dist/engage-memory.js
CHANGED
|
@@ -8,11 +8,6 @@ function resolveConfigsDir() {
|
|
|
8
8
|
if (process.env.SELLABLE_CONFIGS_DIR) {
|
|
9
9
|
candidates.push(path.resolve(process.env.SELLABLE_CONFIGS_DIR));
|
|
10
10
|
}
|
|
11
|
-
// Same resolution strategy as skills.ts
|
|
12
|
-
if (process.argv[1]) {
|
|
13
|
-
candidates.push(path.resolve(path.dirname(process.argv[1]), "../../.sellable/configs"));
|
|
14
|
-
}
|
|
15
|
-
candidates.push(path.resolve(process.cwd(), ".sellable/configs"));
|
|
16
11
|
candidates.push(path.resolve(os.homedir(), ".sellable/configs"));
|
|
17
12
|
for (const candidate of candidates) {
|
|
18
13
|
if (fs.existsSync(candidate)) {
|
package/dist/identity-memory.js
CHANGED
|
@@ -20,10 +20,6 @@ export function resolveIdentityConfigsDir() {
|
|
|
20
20
|
if (process.env.SELLABLE_CONFIGS_DIR) {
|
|
21
21
|
candidates.push(path.resolve(process.env.SELLABLE_CONFIGS_DIR));
|
|
22
22
|
}
|
|
23
|
-
if (process.argv[1]) {
|
|
24
|
-
candidates.push(path.resolve(path.dirname(process.argv[1]), "../../.sellable/configs"));
|
|
25
|
-
}
|
|
26
|
-
candidates.push(path.resolve(process.cwd(), ".sellable/configs"));
|
|
27
23
|
candidates.push(path.resolve(os.homedir(), ".sellable/configs"));
|
|
28
24
|
for (const candidate of candidates) {
|
|
29
25
|
if (fs.existsSync(candidate)) {
|
|
@@ -2,7 +2,7 @@ import { copySenderConfig, getEngageMemory, migrateFlatConfigs, recordProvenSear
|
|
|
2
2
|
export const engageMemoryToolDefinitions = [
|
|
3
3
|
{
|
|
4
4
|
name: "get_engage_memory",
|
|
5
|
-
description: "Load backward-compatible engage memory from
|
|
5
|
+
description: "Load backward-compatible engage memory from ~/.sellable/configs/: style guide, proven search keywords, tracked people, plus optional core identity/company memory. All data lives in readable markdown files the user can also edit directly. When senderId is provided, reads compatibility overrides from senders/{senderId}/ with flat-path fallback.",
|
|
6
6
|
inputSchema: {
|
|
7
7
|
type: "object",
|
|
8
8
|
properties: {
|
|
@@ -17,7 +17,7 @@ export const engageMemoryToolDefinitions = [
|
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
name: "set_engage_style_guide",
|
|
20
|
-
description: "Write the user's commenting style guide. When senderId is provided, writes to
|
|
20
|
+
description: "Write the user's commenting style guide. When senderId is provided, writes to ~/.sellable/configs/senders/{senderId}/styleguide-core.md. Otherwise writes to ~/.sellable/configs/writing/styleguide-core.md.",
|
|
21
21
|
inputSchema: {
|
|
22
22
|
type: "object",
|
|
23
23
|
properties: {
|
package/dist/tools/leads.js
CHANGED
|
@@ -1365,7 +1365,7 @@ export const leadToolDefinitions = [
|
|
|
1365
1365
|
},
|
|
1366
1366
|
limit: {
|
|
1367
1367
|
type: "number",
|
|
1368
|
-
description: "Max posts (default 25, max 50). Used for profile search.",
|
|
1368
|
+
description: "Max posts (default 25, max 50). Used for profile or company search.",
|
|
1369
1369
|
},
|
|
1370
1370
|
headlineICPCriteria: {
|
|
1371
1371
|
type: "array",
|
|
@@ -3177,7 +3177,9 @@ export async function selectPromisingPosts(input) {
|
|
|
3177
3177
|
const { campaignOfferId, selections, headlineICPCriteria, selectionMode, mode, scrapePlanMode, targetEngagerCount, maxPostsToScrape, } = input;
|
|
3178
3178
|
const effectiveMode = selectionMode ?? mode ?? "replace";
|
|
3179
3179
|
const effectiveScrapePlanMode = scrapePlanMode ??
|
|
3180
|
-
(targetEngagerCount || maxPostsToScrape
|
|
3180
|
+
(targetEngagerCount || maxPostsToScrape
|
|
3181
|
+
? "capacity-target"
|
|
3182
|
+
: "all-selected");
|
|
3181
3183
|
if (selections.length > MAX_SIGNAL_DISCOVERY_POSTS) {
|
|
3182
3184
|
return {
|
|
3183
3185
|
success: false,
|
|
@@ -3249,7 +3251,9 @@ export async function selectPromisingPosts(input) {
|
|
|
3249
3251
|
}
|
|
3250
3252
|
const recommendation = buildSignalDiscoverySourceRecommendation({
|
|
3251
3253
|
selectedPosts: Array.from(selectedByUrl.values()),
|
|
3252
|
-
targetEngagerCount: effectiveScrapePlanMode === "capacity-target"
|
|
3254
|
+
targetEngagerCount: effectiveScrapePlanMode === "capacity-target"
|
|
3255
|
+
? targetEngagerCount
|
|
3256
|
+
: null,
|
|
3253
3257
|
maxPostsToScrape: effectiveScrapePlanMode === "capacity-target" ? maxPostsToScrape : null,
|
|
3254
3258
|
});
|
|
3255
3259
|
sourceRecommendation = recommendation.message;
|
package/dist/tools/prompts.js
CHANGED
|
@@ -5,8 +5,8 @@ import { markCreateCampaignPromptLoaded, markResearchPromptLoaded, markSenderRes
|
|
|
5
5
|
// Chunk size sits below Claude Code's max-token cap on tool results
|
|
6
6
|
// (empirically around ~50k chars — fetch_linkedin_profile breached at
|
|
7
7
|
// 53,295 chars, which forced a python3 chunked-read fallback). 48k gives
|
|
8
|
-
// just-enough headroom under the cap. With
|
|
9
|
-
//
|
|
8
|
+
// just-enough headroom under the cap. With the campaign workflow split into
|
|
9
|
+
// entry + generate-message + tail subskills,
|
|
10
10
|
// every individual subskill (including auto-appended SOUL.md) fits in
|
|
11
11
|
// a single 48k chunk → the agent reads the entry prompt in 1 round
|
|
12
12
|
// trip instead of 3-5, dropping first-message latency from ~9-15s to
|
|
@@ -72,7 +72,7 @@ export const promptToolDefinitions = [
|
|
|
72
72
|
subskillName: {
|
|
73
73
|
type: "string",
|
|
74
74
|
enum: ALLOWED_SUBSKILL_PROMPT_NAMES,
|
|
75
|
-
description: "Subskill prompt name. Use generate-messages for message drafting.",
|
|
75
|
+
description: "Subskill prompt name. Use generate-messages for message drafting and row-message generation.",
|
|
76
76
|
},
|
|
77
77
|
offset: {
|
|
78
78
|
type: "number",
|
|
@@ -174,7 +174,7 @@ export const promptToolDefinitions = [
|
|
|
174
174
|
depth: {
|
|
175
175
|
type: "string",
|
|
176
176
|
enum: ["minimal-verification", "deep-proof", "parallel-batch"],
|
|
177
|
-
description: "Research depth used: minimal-verification (proofDigest already had strong signals), deep-proof (extra search agents spawned), or parallel-batch (
|
|
177
|
+
description: "Research depth used: minimal-verification (proofDigest already had strong signals), deep-proof (extra search agents spawned), or parallel-batch (default single 5-call parallel batch with fetch_linkedin_profile + fetch_company + 3x WebSearch).",
|
|
178
178
|
},
|
|
179
179
|
proofItemsFound: {
|
|
180
180
|
type: "number",
|
|
@@ -325,17 +325,23 @@ export function getPostFindLeadsScoutRegistry() {
|
|
|
325
325
|
"startedAt",
|
|
326
326
|
"updatedAt",
|
|
327
327
|
"basisToken",
|
|
328
|
+
"basis.campaignId",
|
|
329
|
+
"basis.selectedLeadListId",
|
|
328
330
|
"basis.workflowTableId",
|
|
329
|
-
"basis.
|
|
331
|
+
"basis.currentExecutionSliceNonEmpty",
|
|
332
|
+
"basis.sampleRows or basis.sampleRowSummary",
|
|
330
333
|
],
|
|
331
|
-
promptRequired: 'Load current campaign brief/table state through scoped tools
|
|
334
|
+
promptRequired: 'Load current campaign brief/table state through scoped tools. Before drafting: get_subskill_prompt({ subskillName: "generate-messages" }); every required message asset named by generate-messages Mode 0 through get_subskill_asset, including gold-standard-message-examples.md, gold-standard-message-patterns.md, ai-tells.md, sellable-cleanup-rules.md, ai-native-tokens.md, and token-fill-examples.md. Do not use shell/local filesystem reads, repo paths, plugin-cache paths, /Users paths, local artifacts, alternate prompts, or examples-only prompts. After candidate generation/revision and before returning ready: get_subskill_prompt({ subskillName: "create-campaign-v2-validation" }) as the final internal validation gate. If required prompts/assets cannot load through MCP tools, return blocked/retry-needed instead of drafting from memory.',
|
|
332
335
|
basisFields: [
|
|
333
336
|
"campaignId",
|
|
337
|
+
"workspace when known",
|
|
338
|
+
"campaignName when useful",
|
|
339
|
+
"selectedLeadListId",
|
|
334
340
|
"workflowTableId",
|
|
335
|
-
"
|
|
336
|
-
"concise
|
|
337
|
-
"
|
|
338
|
-
"
|
|
341
|
+
"filter choice",
|
|
342
|
+
"concise brief summary: offer, buyer, safe proof, blocked claims",
|
|
343
|
+
"concise source summary and source-use rule",
|
|
344
|
+
"3-5 sample campaign-table rows with name, title, company when available, and signal",
|
|
339
345
|
],
|
|
340
346
|
messageDraftOutputFields: [
|
|
341
347
|
"templateRecommendation",
|
|
@@ -351,12 +357,12 @@ export function getPostFindLeadsScoutRegistry() {
|
|
|
351
357
|
"outputHash",
|
|
352
358
|
"error or retry detail",
|
|
353
359
|
],
|
|
354
|
-
reusePolicy: "The first completed Message Drafting recommendation remains the default review candidate. Later
|
|
360
|
+
reusePolicy: "The first completed Message Drafting recommendation remains the default review candidate. Later Lead Fit Builder, Filter Leads, enrichment, or rubric completion may make an enriched rewrite available, but does not automatically retry or replace the initial draft unless campaign/brief/source/list/table/execution-slice identity mismatches or the initial output failed. User copy feedback before approve-message is an explicit Message Drafting revision and must be routed back through the message branch with the current recommendation and basis.",
|
|
355
361
|
},
|
|
356
362
|
usage: {
|
|
357
363
|
codex: "After confirm_lead_list copies source rows and the initial campaign-table execution slice exists, ask the filter-choice question immediately. Do not spawn anything before that question. After the answer, launch only Message Drafting whenever Codex agent-launch policy is satisfied. If filters are chosen, the parent stays on Filter Rules and drafts/saves rubrics with MCP tools while Message Drafting runs in the background. If filters are skipped, move to Messages/message review after Message Drafting is ready. Treat YOLO/autonomous mode as campaign-scoped permission for this single post-import worker. If the user has not enabled YOLO and has not explicitly asked for background agents/subagents/parallel agents/delegation/message bg agent in this campaign, ask once before loading the long message prompt in the parent. If permission is granted and the named Message Drafting custom agent is unavailable, spawn a generic gpt-5.5 xhigh Message Drafting background agent with the same lean campaign/table basis.",
|
|
358
364
|
claude: "After confirm_lead_list copies source rows and the initial campaign-table execution slice exists, ask the filter-choice question immediately. Do not invoke any Task/Agent before that question. After the answer, invoke only Message Drafting. If filters are chosen, parent drafts/saves rubrics with MCP tools while Message Drafting runs, asks filter approval, then joins Message Drafting. If filters are skipped, invoke only Message Drafting and move to Messages/message review.",
|
|
359
|
-
parentThreadRule: '
|
|
365
|
+
parentThreadRule: 'Named agents are optional acceleration, but message drafting is not optional. The only normal background worker is Message Drafting. YOLO/autonomous mode counts as campaign-scoped permission for this single post-import worker. If a named agent is unavailable after permission, use a generic gpt-5.5 xhigh Message Drafting background agent. source work and filter work stay in the parent thread with MCP tools. If post-find-leads-message-scout is available, run it as the background Message Draft Builder after the filter-choice answer. If it is absent, do not customer-surface install status. Do not silently fall back to parent-thread message drafting; the main thread must execute the same message branch from CampaignOffer state, selected source state, workflowTableId, and initial campaign-table execution slice rows. The Message Drafting handoff must be lean. Do not paste copied row counts, brief hashes, review-batch hashes, full reviewBatchRowIds, broad row data, or local debug artifacts into the spawn prompt. Local markdown/json files are not normal-path inputs. The filter-choice question is the first post-import user gate; do not load post-lead registries or filter references before it. Message drafting starts after the filter-choice answer, must load get_subskill_prompt({ subskillName: "generate-messages" }), and must load every required message asset named by generate-messages Mode 0 through get_subskill_asset before drafting. Reference Asset Loading means loading the required pre-draft reference pack before drafting; return blocked/retry-needed if required assets cannot be loaded; load ai-tells.md because it is never optional. The branch loads the full generate-messages prompt and every referenced asset through get_subskill_asset. After generating/revising the candidate and before returning ready, must load get_subskill_prompt({ subskillName: "create-campaign-v2-validation" }) as the final internal validation gate, must read live campaign table state through scoped MCP/product tools, and must reject mismatched selectedLeadListId/workflowTableId/campaign/workspace input. Do not use any alternate, local-artifact, or examples-only message prompt. User copy feedback, message QA, or rewrite requests before approve-message must be routed back to Message Drafting with the current recommendation, lean campaign/table basis, and latest user text; the parent must not rewrite or QA the template from memory and must not call update_campaign_brief before approve-message. The worker validates internally and returns only templateRecommendation, tokenFillRules, renderedGoodSample, status, approveOrReviseRecommendation, validationStatus, outputAt, outputHash, and blocked/retry detail. Do not render renderedFallbackSample, risk notes, or a qaReceipt on the normal happy path. On the filter path, save_rubrics keeps the browser on Filter Rules after save_rubrics so the user can approve the saved criteria; only then move to Filter Leads, show `Filters saved + waiting for message approval`, and wait there for message approval. Enrichment, filtering, Generate Message cells, sender setup, sequence attach, and launch wait for template approval on the Use Template path. On the skip path, move to Messages/message review and wait for message approval before enrichment or Settings. Do not render message review from checklist or shortcut instructions; message review requires a messageDraftRecommendation whose basis proves the generate-messages prompt, required message assets, and validation gate ran for the current campaign/table execution slice. Do not automatically rerun Message Drafting after filters/enrichment finish; show the initial draft by default and offer an enriched rewrite only with explicit user opt-in. Handoff and recommendation output are Markdown with labeled fields, not raw JSON.',
|
|
360
366
|
},
|
|
361
367
|
};
|
|
362
368
|
}
|