@sellable/mcp 0.1.238 → 0.1.240
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/dist/tools/content-posts.d.ts +8 -0
- package/dist/tools/content-posts.js +23 -7
- package/dist/tools/registry.d.ts +2 -0
- package/package.json +2 -1
- package/skills/create-campaign-v2/references/validation-criteria.md +4 -4
- package/skills/create-post/SKILL.md +182 -13
- package/skills/create-post/references/gold-standard-post-pack.md +51 -2
- package/skills/create-post/references/hook-research-playbook.md +191 -2
- package/skills/create-post/references/post-file-contract.md +5 -1
- package/skills/create-post/references/post-validation.md +28 -7
- package/skills/generate-messages/SKILL.md +5 -0
|
@@ -58,6 +58,7 @@ export declare const contentPostToolDefinitions: ({
|
|
|
58
58
|
keywords?: undefined;
|
|
59
59
|
sourcePosts?: undefined;
|
|
60
60
|
selectedPatterns?: undefined;
|
|
61
|
+
previewBudget?: undefined;
|
|
61
62
|
notes?: undefined;
|
|
62
63
|
createdAt?: undefined;
|
|
63
64
|
draftId?: undefined;
|
|
@@ -130,6 +131,11 @@ export declare const contentPostToolDefinitions: ({
|
|
|
130
131
|
type: string;
|
|
131
132
|
};
|
|
132
133
|
};
|
|
134
|
+
previewBudget: {
|
|
135
|
+
type: string;
|
|
136
|
+
description: string;
|
|
137
|
+
additionalProperties: boolean;
|
|
138
|
+
};
|
|
133
139
|
notes: {
|
|
134
140
|
type: string;
|
|
135
141
|
};
|
|
@@ -192,6 +198,7 @@ export declare const contentPostToolDefinitions: ({
|
|
|
192
198
|
keywords?: undefined;
|
|
193
199
|
sourcePosts?: undefined;
|
|
194
200
|
selectedPatterns?: undefined;
|
|
201
|
+
previewBudget?: undefined;
|
|
195
202
|
notes?: undefined;
|
|
196
203
|
};
|
|
197
204
|
required: string[];
|
|
@@ -245,6 +252,7 @@ export declare function saveHookResearchTool(input: {
|
|
|
245
252
|
keywords?: string[];
|
|
246
253
|
sourcePosts?: Array<Record<string, unknown>>;
|
|
247
254
|
selectedPatterns?: string[];
|
|
255
|
+
previewBudget?: Record<string, unknown>;
|
|
248
256
|
notes?: string;
|
|
249
257
|
createdAt?: string;
|
|
250
258
|
}): {
|
|
@@ -66,6 +66,11 @@ export const contentPostToolDefinitions = [
|
|
|
66
66
|
type: "array",
|
|
67
67
|
items: { type: "string" },
|
|
68
68
|
},
|
|
69
|
+
previewBudget: {
|
|
70
|
+
type: "object",
|
|
71
|
+
description: "Optional structured LinkedIn preview-budget summary for studied hooks and selected patterns.",
|
|
72
|
+
additionalProperties: true,
|
|
73
|
+
},
|
|
69
74
|
notes: { type: "string" },
|
|
70
75
|
createdAt: { type: "string" },
|
|
71
76
|
},
|
|
@@ -202,11 +207,14 @@ export function capturePostIdeaTool(input) {
|
|
|
202
207
|
const markdown = buildMarkdown(metadata, [
|
|
203
208
|
["Distilled Brief", input.distilledBrief || ""],
|
|
204
209
|
["Raw Source", rawBlock(input.rawSource)],
|
|
205
|
-
[
|
|
210
|
+
[
|
|
211
|
+
"Source Metadata",
|
|
212
|
+
jsonBlock(stripUndefined({
|
|
206
213
|
sourceType: input.sourceType,
|
|
207
214
|
sourceUrl: input.sourceUrl,
|
|
208
215
|
capturedAt: now,
|
|
209
|
-
}))
|
|
216
|
+
})),
|
|
217
|
+
],
|
|
210
218
|
]);
|
|
211
219
|
writeArtifact(relativePath, markdown);
|
|
212
220
|
return {
|
|
@@ -246,6 +254,7 @@ export function saveHookResearchTool(input) {
|
|
|
246
254
|
const markdown = buildMarkdown(metadata, [
|
|
247
255
|
["Keywords", listBlock(input.keywords ?? [])],
|
|
248
256
|
["Selected Patterns", listBlock(input.selectedPatterns ?? [])],
|
|
257
|
+
["Preview Budget", jsonBlock(input.previewBudget ?? {})],
|
|
249
258
|
["Source Posts", jsonBlock(input.sourcePosts ?? [])],
|
|
250
259
|
["Notes", input.notes || ""],
|
|
251
260
|
]);
|
|
@@ -332,18 +341,24 @@ export function markPostPublishedTool(input) {
|
|
|
332
341
|
};
|
|
333
342
|
const markdown = buildMarkdown(metadata, [
|
|
334
343
|
["Final Text", input.finalText || ""],
|
|
335
|
-
[
|
|
344
|
+
[
|
|
345
|
+
"Publish Metadata",
|
|
346
|
+
jsonBlock(stripUndefined({
|
|
336
347
|
draftId: safeDraftId,
|
|
337
348
|
publishUrl: input.publishUrl,
|
|
338
349
|
activityId: activityId || undefined,
|
|
339
350
|
publishedAt,
|
|
340
|
-
}))
|
|
341
|
-
|
|
351
|
+
})),
|
|
352
|
+
],
|
|
353
|
+
[
|
|
354
|
+
"Future Metrics",
|
|
355
|
+
jsonBlock({
|
|
342
356
|
impressions: null,
|
|
343
357
|
reactions: null,
|
|
344
358
|
comments: null,
|
|
345
359
|
snapshots: [],
|
|
346
|
-
})
|
|
360
|
+
}),
|
|
361
|
+
],
|
|
347
362
|
]);
|
|
348
363
|
writeArtifact(relativePath, markdown);
|
|
349
364
|
return {
|
|
@@ -483,7 +498,8 @@ function validateRelativePath(relativePath) {
|
|
|
483
498
|
}
|
|
484
499
|
function isPathInside(candidate, root) {
|
|
485
500
|
const relative = path.relative(root, candidate);
|
|
486
|
-
return relative === "" ||
|
|
501
|
+
return (relative === "" ||
|
|
502
|
+
(!relative.startsWith("..") && !path.isAbsolute(relative)));
|
|
487
503
|
}
|
|
488
504
|
function normalizeArtifactId(id, label) {
|
|
489
505
|
requireString(id, label);
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -1214,6 +1214,7 @@ export declare const allTools: ({
|
|
|
1214
1214
|
keywords?: undefined;
|
|
1215
1215
|
sourcePosts?: undefined;
|
|
1216
1216
|
selectedPatterns?: undefined;
|
|
1217
|
+
previewBudget?: undefined;
|
|
1217
1218
|
notes?: undefined;
|
|
1218
1219
|
createdAt?: undefined;
|
|
1219
1220
|
draftId?: undefined;
|
|
@@ -1279,6 +1280,7 @@ export declare const allTools: ({
|
|
|
1279
1280
|
keywords?: undefined;
|
|
1280
1281
|
sourcePosts?: undefined;
|
|
1281
1282
|
selectedPatterns?: undefined;
|
|
1283
|
+
previewBudget?: undefined;
|
|
1282
1284
|
notes?: undefined;
|
|
1283
1285
|
};
|
|
1284
1286
|
required: string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sellable/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.240",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Sellable MCP server for Claude Code and Codex campaign workflows",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "tsc",
|
|
14
|
+
"prepack": "npm run build",
|
|
14
15
|
"start": "node dist/index.js",
|
|
15
16
|
"start:dev": "node dist/index-dev.js",
|
|
16
17
|
"dev": "ts-node src/index.ts"
|
|
@@ -93,10 +93,10 @@ Required:
|
|
|
93
93
|
select a blocked candidate. If all 3 candidates fail, route to
|
|
94
94
|
`revise-message` with the failure reasons enumerated per candidate (cite the
|
|
95
95
|
rule/filter name and the offending line).
|
|
96
|
-
- **Concrete Language Audit.** The selected draft must highlight every abstract
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
- **Concrete Language Audit.** The selected draft must highlight every abstract verb,
|
|
97
|
+
abstract noun, abstract adjective, abstract adverb, and cliche, then either
|
|
98
|
+
replace it with a buyer-visible action, object, workflow, artifact, risk,
|
|
99
|
+
result, or next step from the approved evidence, cut it, or block with
|
|
100
100
|
`revise-message` / `revise-filter`. Do not leave a vague phrase in place just
|
|
101
101
|
because it sounds polished.
|
|
102
102
|
|
|
@@ -20,7 +20,7 @@ Hard fail patterns:
|
|
|
20
20
|
- drafts that skip raw idea capture
|
|
21
21
|
- hooks copied verbatim from another creator
|
|
22
22
|
- using `~/.sellable/configs/content/linkedin-posts-drafts.md` as the normal save target
|
|
23
|
-
</role>
|
|
23
|
+
</role>
|
|
24
24
|
|
|
25
25
|
<scope>
|
|
26
26
|
V1 is posts-only and hooks-first.
|
|
@@ -42,7 +42,7 @@ Do not:
|
|
|
42
42
|
- optimize a comment workflow
|
|
43
43
|
- move identity/proof/story memory into content files
|
|
44
44
|
- append new drafts to the legacy flat file
|
|
45
|
-
</scope>
|
|
45
|
+
</scope>
|
|
46
46
|
|
|
47
47
|
<required_assets>
|
|
48
48
|
Before drafting, load all required assets with `mcp__sellable__get_subskill_asset`:
|
|
@@ -82,6 +82,7 @@ Use these MCP tools when available:
|
|
|
82
82
|
- `mcp__sellable__fetch_linkedin_posts`
|
|
83
83
|
- `mcp__sellable__fetch_linkedin_profile`
|
|
84
84
|
- `mcp__sellable__record_engage_proven_search`
|
|
85
|
+
- `mcp__sellable__upsert_engage_tracked_person`
|
|
85
86
|
|
|
86
87
|
Do not call outbound/campaign tools from this skill. Do not call message-generation prompts or tools. This skill reuses the quality architecture of the message pipeline: required assets, candidate set, finalizer pass, simplifier/concrete-language audit, anti-AI audit, proof/voice validation, and blocked/retry-needed states.
|
|
87
88
|
</tools>
|
|
@@ -90,7 +91,7 @@ Do not call outbound/campaign tools from this skill. Do not call message-generat
|
|
|
90
91
|
Load user memory before hook generation or drafting:
|
|
91
92
|
|
|
92
93
|
1. Call `mcp__sellable__get_engage_memory`.
|
|
93
|
-
2. Read or use the returned core memory fields:
|
|
94
|
+
2. Read or use the returned core identity memory and company memory fields:
|
|
94
95
|
- `core/about-me.md`
|
|
95
96
|
- `core/my-company.md`
|
|
96
97
|
- `core/anti-ai-writing-style.md`
|
|
@@ -115,6 +116,39 @@ Load user memory before hook generation or drafting:
|
|
|
115
116
|
New users may have blank or missing core files until they run `$sellable:interview`. If story, proof, identity, or company memory is missing, ask for the missing material or ask the user to run `$sellable:interview`. Never fabricate what should have come from `story-bank.md`, `proof-ledger.md`, or `answer-bank.md`.
|
|
116
117
|
|
|
117
118
|
The interview/core memory files remain the durable source for stories and proof. This skill may read them, but it must not move them into `~/.sellable/content/**`.
|
|
119
|
+
|
|
120
|
+
Use core context modes as drafting constraints, not decorative labels. If a
|
|
121
|
+
post idea exposes durable memory that should help future writing, propose a
|
|
122
|
+
core write-back before saving it. The user must be able to approve, edit, or
|
|
123
|
+
reject each proposed memory update before it is written.
|
|
124
|
+
|
|
125
|
+
Durable write-back targets:
|
|
126
|
+
|
|
127
|
+
- `core/answer-bank.md` for reusable user answers, positioning, or taste rules
|
|
128
|
+
- `core/wins-ledger.md` for verified wins and outcomes
|
|
129
|
+
- `core/change-log.md` for approved corrections, rejected-but-useful proposals,
|
|
130
|
+
privacy decisions, and downstream prompt/operator notes
|
|
131
|
+
- `core/story-bank.md` for reusable first-person stories
|
|
132
|
+
- `core/transcripts/INDEX.md` for source interview or voice-memo references
|
|
133
|
+
- `core/references/linkedin-posts/INDEX.md` and adjacent files for approved
|
|
134
|
+
gold-standard post references
|
|
135
|
+
- `discovery/influencers.md` for approved creators/persons the user wants the
|
|
136
|
+
system to keep learning from
|
|
137
|
+
|
|
138
|
+
Write-backs must use stable source keys such as
|
|
139
|
+
`create-post:{date}:{ideaId}:{slug}` or
|
|
140
|
+
`create-post-research:{date}:{sourcePostHash}:{slug}`. Check existing copied
|
|
141
|
+
paths before adding references, create no duplicate reference rows, and keep
|
|
142
|
+
manual sections preserved. If the user says to mark private, store only the
|
|
143
|
+
minimum private-safe metadata and do not promote it into public proof,
|
|
144
|
+
references, or examples.
|
|
145
|
+
|
|
146
|
+
When the user says a creator/person is worth following, learning from, or using
|
|
147
|
+
again, persist them with `mcp__sellable__upsert_engage_tracked_person` before
|
|
148
|
+
continuing. Use the canonical LinkedIn profile URL, a concise reason that names
|
|
149
|
+
the content lane, and no senderId unless the user explicitly scopes the person
|
|
150
|
+
to one sender. If the person is already tracked, update the reason instead of
|
|
151
|
+
creating a duplicate.
|
|
118
152
|
</memory_contract>
|
|
119
153
|
|
|
120
154
|
<modes>
|
|
@@ -149,6 +183,29 @@ Normal ad hoc mode still creates an ID'd idea artifact first with `mcp__sellable
|
|
|
149
183
|
|
|
150
184
|
If the user explicitly says not to save anything, label the output `unsaved_preview`, do not call it draft-ready, and do not mark it as validated for publishing.
|
|
151
185
|
|
|
186
|
+
## Research Checkpoint Mode
|
|
187
|
+
|
|
188
|
+
Use when the user asks to research hooks, research bodies, "show me what it
|
|
189
|
+
learned", "run the research phase", "what is working in the space", or anything
|
|
190
|
+
similar.
|
|
191
|
+
|
|
192
|
+
1. Capture or load the idea/topic if one is provided.
|
|
193
|
+
2. Run the hook/body research playbook.
|
|
194
|
+
3. Save the research with `mcp__sellable__save_hook_research`.
|
|
195
|
+
4. Present a `Research Learning Report` to the user.
|
|
196
|
+
5. Do not draft until the user approves a direction or explicitly says to run
|
|
197
|
+
the draft phase.
|
|
198
|
+
|
|
199
|
+
The report must include specific words, phrase shapes, sentence patterns, and
|
|
200
|
+
body moves from the research. Do not only report abstract labels like
|
|
201
|
+
"contrarian hook" or "tool-stack enemy."
|
|
202
|
+
|
|
203
|
+
When the host supports background agents or Task workers, run the heavy research
|
|
204
|
+
in a dedicated research worker so the main orchestrator stays clean. The
|
|
205
|
+
orchestrator should keep only the compressed research packet, final selected
|
|
206
|
+
examples, and user-facing learning report in context. Do not paste the entire
|
|
207
|
+
raw source-post corpus into the orchestrator conversation.
|
|
208
|
+
|
|
152
209
|
## Gold Standard Pack Mode
|
|
153
210
|
|
|
154
211
|
Use when the user asks to import their best posts, research best posts in the space, build a gold-standard pack, or add inspiration examples.
|
|
@@ -169,8 +226,11 @@ Space benchmark research:
|
|
|
169
226
|
1. Use `mcp__sellable__search_engagement_posts` and the hook research playbook.
|
|
170
227
|
2. Shortlist high-performing posts from the user's space using the weighted signal rules.
|
|
171
228
|
3. Penalize lead magnets, giveaways, engagement bait, celebrity-only reach, and poor voice fit.
|
|
172
|
-
4.
|
|
173
|
-
|
|
229
|
+
4. When a creator/person appears repeatedly strong, include a `track_person`
|
|
230
|
+
recommendation in the candidate card.
|
|
231
|
+
5. Show the user the candidates and ask: "These look good. Should we use any as gold standards or track any of these people?"
|
|
232
|
+
6. Add only the user-approved post selections.
|
|
233
|
+
7. For each approved tracked person, call `mcp__sellable__upsert_engage_tracked_person`.
|
|
174
234
|
|
|
175
235
|
The approved pack is capped at 20 gold standards. If adding new approved examples would exceed 20, ask which existing item to replace or skip the overflow. Candidate lists can be longer, but approved saved standards cannot exceed 20.
|
|
176
236
|
</modes>
|
|
@@ -196,6 +256,27 @@ If local idea capture succeeds but auth/workspace is missing, keep the idea and
|
|
|
196
256
|
|
|
197
257
|
Use `references/hook-research-playbook.md`.
|
|
198
258
|
|
|
259
|
+
If the host supports background agents, delegate the search/fetch/autopsy work
|
|
260
|
+
to one bounded `research-worker` before hook candidate generation. The worker
|
|
261
|
+
owns broad search, profile fetches, full-text matching, source filtering,
|
|
262
|
+
language extraction, and body-structure extraction. The orchestrator owns the
|
|
263
|
+
final save call, user-visible `Research Learning Report`, direction selection,
|
|
264
|
+
and drafting gate.
|
|
265
|
+
|
|
266
|
+
The research worker must return a compact packet only:
|
|
267
|
+
|
|
268
|
+
- source examples kept and rejected
|
|
269
|
+
- full adapted hook blocks
|
|
270
|
+
- exact phrase patterns and sentence shapes
|
|
271
|
+
- body structures and exact body language moves
|
|
272
|
+
- preview measurements
|
|
273
|
+
- track-person and gold-standard recommendations
|
|
274
|
+
- blocked states or confidence gaps
|
|
275
|
+
|
|
276
|
+
The research worker must not return all raw post bodies unless a specific full
|
|
277
|
+
text is required as a gold-standard candidate. Prefer summaries plus URLs and
|
|
278
|
+
the exact extracted phrase shapes.
|
|
279
|
+
|
|
199
280
|
Default flow:
|
|
200
281
|
|
|
201
282
|
1. Convert the idea into 3-8 search keywords.
|
|
@@ -206,7 +287,8 @@ Default flow:
|
|
|
206
287
|
6. Weigh shares/reposts above comments, comments above reactions, and reactions as weak reach unless paired with stronger signals. If shares/reposts are unavailable, record `repost_data_unavailable`.
|
|
207
288
|
7. Penalize lead-magnet or giveaway mechanics unless the user explicitly asks for a lead magnet post.
|
|
208
289
|
8. For story posts, extract the story mechanism that made the post work, not just the first line.
|
|
209
|
-
9. Extract hook structures,
|
|
290
|
+
9. Extract hook structures plus specific reusable words, phrases, sentence
|
|
291
|
+
shapes, transitions, and body language patterns.
|
|
210
292
|
10. Save the research with `mcp__sellable__save_hook_research`.
|
|
211
293
|
|
|
212
294
|
Record provenance:
|
|
@@ -221,9 +303,79 @@ Record provenance:
|
|
|
221
303
|
- lead-magnet or engagement-bait penalties
|
|
222
304
|
- story mechanism when relevant
|
|
223
305
|
- full-text match status
|
|
306
|
+
- source hook preview measurements and whether they came from full text or a search preview
|
|
224
307
|
- selected hook patterns
|
|
308
|
+
- exact phrase patterns and sentence shapes
|
|
309
|
+
- body structures and body language patterns
|
|
225
310
|
- why each pattern fits the user's idea and voice
|
|
226
311
|
|
|
312
|
+
## Step 1.5: Research Learning Report
|
|
313
|
+
|
|
314
|
+
After saving research and before drafting, show the user what the system
|
|
315
|
+
learned when either:
|
|
316
|
+
|
|
317
|
+
- the user asked for research/checkpoint mode
|
|
318
|
+
- the research materially changes the likely hook/body direction
|
|
319
|
+
- the researched examples include new people worth tracking or examples worth
|
|
320
|
+
adding as gold standards
|
|
321
|
+
|
|
322
|
+
Default ad hoc drafting may proceed after this report only when the user clearly
|
|
323
|
+
asked for an immediate draft. In research checkpoint mode, stop here and ask
|
|
324
|
+
which direction to use.
|
|
325
|
+
|
|
326
|
+
The `Research Learning Report` must include:
|
|
327
|
+
|
|
328
|
+
```text
|
|
329
|
+
Research status:
|
|
330
|
+
- idea/topic:
|
|
331
|
+
- research artifact:
|
|
332
|
+
- search window:
|
|
333
|
+
- keywords:
|
|
334
|
+
- full-text coverage:
|
|
335
|
+
- repost/share data:
|
|
336
|
+
|
|
337
|
+
Best source examples:
|
|
338
|
+
1. author, URL, engagement, why kept, why not copied
|
|
339
|
+
|
|
340
|
+
Hook patterns learned:
|
|
341
|
+
1. full adapted hook block
|
|
342
|
+
- source mechanism:
|
|
343
|
+
- preview budget:
|
|
344
|
+
- internal question:
|
|
345
|
+
- why it fits / why it does not:
|
|
346
|
+
|
|
347
|
+
Specific words and phrase shapes:
|
|
348
|
+
1. "phrase or phrase shape"
|
|
349
|
+
- role:
|
|
350
|
+
- source:
|
|
351
|
+
- reusable forms:
|
|
352
|
+
- adapted Sellable form:
|
|
353
|
+
- do not copy:
|
|
354
|
+
|
|
355
|
+
Body structures learned:
|
|
356
|
+
1. structure name
|
|
357
|
+
- source:
|
|
358
|
+
- sequence:
|
|
359
|
+
- exact language moves:
|
|
360
|
+
- adapted Sellable body move:
|
|
361
|
+
|
|
362
|
+
Rejected examples:
|
|
363
|
+
- author/source:
|
|
364
|
+
- reason rejected:
|
|
365
|
+
|
|
366
|
+
Save recommendations:
|
|
367
|
+
- track people:
|
|
368
|
+
- gold-standard candidates:
|
|
369
|
+
|
|
370
|
+
Recommended draft directions:
|
|
371
|
+
1. hook block + body structure
|
|
372
|
+
2. hook block + body structure
|
|
373
|
+
3. hook block + body structure
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
Keep this report concise enough to read, but concrete enough that another agent
|
|
377
|
+
could draft from it without redoing research.
|
|
378
|
+
|
|
227
379
|
## Step 2: Hook Candidates
|
|
228
380
|
|
|
229
381
|
Generate at least 12 hook candidates unless the user requested a smaller set.
|
|
@@ -233,8 +385,14 @@ Each hook must include:
|
|
|
233
385
|
- source hook pattern
|
|
234
386
|
- why it fits this idea
|
|
235
387
|
- `charCount`
|
|
388
|
+
- `charCountIncludingNewlines`
|
|
236
389
|
- `firstLineChars`
|
|
237
390
|
- `firstTwoLinesChars`
|
|
391
|
+
- `physicalLineCount`
|
|
392
|
+
- `contentLineCount`
|
|
393
|
+
- `longestNonblankLineChars`
|
|
394
|
+
- `blankLineVisualRisk`
|
|
395
|
+
- `previewBudgetStatus`
|
|
238
396
|
- `mobilePreviewFit`
|
|
239
397
|
- `desktopPreviewFit`
|
|
240
398
|
- `lineCountEstimate`
|
|
@@ -246,14 +404,22 @@ Each hook must include:
|
|
|
246
404
|
|
|
247
405
|
Do not copy source wording. Copy only the structure.
|
|
248
406
|
|
|
249
|
-
Use
|
|
407
|
+
Use this conservative mobile-first LinkedIn preview gate. LinkedIn does not
|
|
408
|
+
publish exact "see more" cutoff rules, and rendering varies by device, app
|
|
409
|
+
version, font, media, and line break. These are v1 safety budgets, not claims
|
|
410
|
+
about an official LinkedIn limit:
|
|
411
|
+
|
|
412
|
+
- `pass`: hook is <= 110 chars including newlines, every nonblank line is <= 45 chars, and the hook's core point lands before likely truncation.
|
|
413
|
+
- `warn`: hook is 111-140 chars including newlines, any nonblank line is 46-55 chars, or blank lines create visual-line risk. Blank lines are allowed, but they count as physical lines.
|
|
414
|
+
- `fail`: hook is > 140 chars including newlines, any nonblank line is > 55 chars, or the hook's point depends on text after likely truncation.
|
|
250
415
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
- desktop first line: 70-90 chars
|
|
254
|
-
- desktop first two lines: 140-180 chars
|
|
416
|
+
Desktop preview usually has more room. Still record `desktopPreviewFit`, but
|
|
417
|
+
never let desktop fit compensate for a mobile `fail`.
|
|
255
418
|
|
|
256
|
-
If a hook's point depends on text after the likely preview, rewrite it before
|
|
419
|
+
If a hook's point depends on text after the likely preview, rewrite it before
|
|
420
|
+
selecting it. A selected hook may carry a `warn` only when the warning is about
|
|
421
|
+
intentional blank-line rhythm or a slight line-length overage; include a compact
|
|
422
|
+
fallback in the validation receipt.
|
|
257
423
|
|
|
258
424
|
## Step 3: Draft
|
|
259
425
|
|
|
@@ -287,6 +453,7 @@ Every saved draft needs a validation receipt with:
|
|
|
287
453
|
- voice audit findings
|
|
288
454
|
- anti-AI audit findings
|
|
289
455
|
- outbound AI-tell audit findings
|
|
456
|
+
- hook preview pass/warn/fail status and compact fallback when warned
|
|
290
457
|
- finalizer changes
|
|
291
458
|
- blocked/retry-needed reasons, if any
|
|
292
459
|
|
|
@@ -319,6 +486,7 @@ Published post records live under:
|
|
|
319
486
|
```text
|
|
320
487
|
~/.sellable/content/linkedin/published/
|
|
321
488
|
```
|
|
489
|
+
|
|
322
490
|
</pipeline>
|
|
323
491
|
|
|
324
492
|
<legacy>
|
|
@@ -341,8 +509,9 @@ validation_summary:
|
|
|
341
509
|
proof: pass | needs_user_input | blocked
|
|
342
510
|
voice: pass | needs_revision
|
|
343
511
|
anti_ai: pass | needs_revision
|
|
344
|
-
linkedin_preview: pass | needs_revision
|
|
512
|
+
linkedin_preview: pass | warn | needs_revision
|
|
345
513
|
concrete_language: pass | needs_revision
|
|
346
514
|
next_step: <what the user should do next>
|
|
347
515
|
```
|
|
516
|
+
|
|
348
517
|
</response_shape>
|
|
@@ -35,6 +35,42 @@ Do not store gold standards under `~/.sellable/content/linkedin/**`. Content
|
|
|
35
35
|
folders are for ideas, hook research, drafts, published records, and future
|
|
36
36
|
comment history. Gold standards are durable writing memory.
|
|
37
37
|
|
|
38
|
+
## Creator Tracking
|
|
39
|
+
|
|
40
|
+
When an outside creator/person is approved as someone the user wants to keep
|
|
41
|
+
learning from, save the person separately from the gold-standard post.
|
|
42
|
+
|
|
43
|
+
Use:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
mcp__sellable__upsert_engage_tracked_person({
|
|
47
|
+
name,
|
|
48
|
+
linkedinUrl,
|
|
49
|
+
reason
|
|
50
|
+
})
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Tracked people live in:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
~/.sellable/configs/discovery/influencers.md
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Gold-standard post records live in:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
~/.sellable/configs/core/references/linkedin-posts/
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Save both when both are approved:
|
|
66
|
+
|
|
67
|
+
- tracked person: "keep fetching this creator's new posts"
|
|
68
|
+
- gold-standard post: "use this specific post as decomposed writing memory"
|
|
69
|
+
|
|
70
|
+
Do not conflate the two. A person can be tracked without any one post becoming
|
|
71
|
+
a gold standard, and a post can be saved as a gold standard without tracking the
|
|
72
|
+
author.
|
|
73
|
+
|
|
38
74
|
## Import Modes
|
|
39
75
|
|
|
40
76
|
### Personal Best Import
|
|
@@ -65,7 +101,11 @@ gold standards.
|
|
|
65
101
|
reach, and examples that cannot be adapted to the user's voice.
|
|
66
102
|
5. Present candidates with a clear "should we use these as gold standards?"
|
|
67
103
|
approval gate.
|
|
68
|
-
6.
|
|
104
|
+
6. Include a `track person?` recommendation for authors with repeated strong
|
|
105
|
+
topic-fit posts or when the user says they like the person.
|
|
106
|
+
7. Add only the user-approved post selections.
|
|
107
|
+
8. Call `mcp__sellable__upsert_engage_tracked_person` only for user-approved
|
|
108
|
+
tracked people.
|
|
69
109
|
|
|
70
110
|
## Candidate Presentation
|
|
71
111
|
|
|
@@ -78,6 +118,7 @@ Show compact candidate cards. Include:
|
|
|
78
118
|
- engagement breakdown when available
|
|
79
119
|
- why it might belong in the pack
|
|
80
120
|
- hook mechanism
|
|
121
|
+
- hook preview budget status and measurement basis
|
|
81
122
|
- content/body mechanism
|
|
82
123
|
- rhythm notes
|
|
83
124
|
- sentence-structure notes
|
|
@@ -85,6 +126,7 @@ Show compact candidate cards. Include:
|
|
|
85
126
|
- voice fit
|
|
86
127
|
- risks
|
|
87
128
|
- allowed use recommendation
|
|
129
|
+
- track person recommendation and reason
|
|
88
130
|
|
|
89
131
|
Approval prompt:
|
|
90
132
|
|
|
@@ -92,7 +134,7 @@ Approval prompt:
|
|
|
92
134
|
Gold-standard pack: <current_count>/20 approved.
|
|
93
135
|
|
|
94
136
|
These look like candidates worth saving. Which should I add?
|
|
95
|
-
Reply with numbers to add, "skip all", or "replace <existing> with <new>" if the pack is full.
|
|
137
|
+
Reply with numbers to add, "track <author>", "skip all", or "replace <existing> with <new>" if the pack is full.
|
|
96
138
|
```
|
|
97
139
|
|
|
98
140
|
Do not write candidates to the approved pack before the user chooses.
|
|
@@ -144,8 +186,15 @@ Tags:
|
|
|
144
186
|
|
|
145
187
|
- hook text:
|
|
146
188
|
- char count:
|
|
189
|
+
- char count including newlines:
|
|
147
190
|
- first-line chars:
|
|
148
191
|
- first-two-line chars:
|
|
192
|
+
- physical line count:
|
|
193
|
+
- content line count:
|
|
194
|
+
- longest nonblank line chars:
|
|
195
|
+
- blank-line visual risk:
|
|
196
|
+
- source text basis:
|
|
197
|
+
- preview budget status:
|
|
149
198
|
- mobile preview fit:
|
|
150
199
|
- desktop preview fit:
|
|
151
200
|
- hook mechanism:
|
|
@@ -11,6 +11,58 @@ Derive 3-8 keyword searches from:
|
|
|
11
11
|
- proven search terms in engage memory
|
|
12
12
|
- tracked people/inspiration references when relevant
|
|
13
13
|
|
|
14
|
+
When research reveals a creator/person the user likes, keep their profile URL
|
|
15
|
+
with the source post. If the user approves tracking them, save them with
|
|
16
|
+
`mcp__sellable__upsert_engage_tracked_person` so future sessions can fetch
|
|
17
|
+
their posts directly instead of rediscovering them ad hoc.
|
|
18
|
+
|
|
19
|
+
## Background Research Worker
|
|
20
|
+
|
|
21
|
+
Use a background research worker when the host supports it and the research
|
|
22
|
+
needs more than a small handful of posts. This keeps the main orchestrator
|
|
23
|
+
focused on decisions instead of carrying a large source corpus.
|
|
24
|
+
|
|
25
|
+
Worker owns:
|
|
26
|
+
|
|
27
|
+
- broad keyword search
|
|
28
|
+
- tracked-person post fetches
|
|
29
|
+
- full-text matching by URL/activity ID
|
|
30
|
+
- duplicate removal
|
|
31
|
+
- lead-magnet, giveaway, engagement-bait, and off-voice filtering
|
|
32
|
+
- hook opening measurement
|
|
33
|
+
- exact phrase-pattern extraction
|
|
34
|
+
- body-structure extraction
|
|
35
|
+
- rejected-example notes
|
|
36
|
+
- track-person and gold-standard recommendations
|
|
37
|
+
|
|
38
|
+
Orchestrator owns:
|
|
39
|
+
|
|
40
|
+
- deciding whether research is enough
|
|
41
|
+
- saving `mcp__sellable__save_hook_research`
|
|
42
|
+
- showing the `Research Learning Report`
|
|
43
|
+
- asking which direction to draft
|
|
44
|
+
- drafting and validation
|
|
45
|
+
|
|
46
|
+
Worker output must be a compressed research packet, not a data dump:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
Research packet:
|
|
50
|
+
- sources kept: max 8
|
|
51
|
+
- sources rejected: max 8
|
|
52
|
+
- full adapted hook blocks: max 12
|
|
53
|
+
- exact phrase patterns: max 20
|
|
54
|
+
- body patterns: max 8
|
|
55
|
+
- source URLs and author profile URLs
|
|
56
|
+
- preview measurements
|
|
57
|
+
- confidence gaps
|
|
58
|
+
- save recommendations
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Do not return the full raw text of every post to the orchestrator. Include only
|
|
62
|
+
short source excerpts needed to explain a phrase pattern, plus URLs. Full text
|
|
63
|
+
belongs in the saved research artifact only when the user approves a specific
|
|
64
|
+
gold-standard candidate and it is safe to store.
|
|
65
|
+
|
|
14
66
|
## Default Search
|
|
15
67
|
|
|
16
68
|
Use `mcp__sellable__search_engagement_posts` with practical constraints:
|
|
@@ -74,19 +126,65 @@ When full hook/body text matters:
|
|
|
74
126
|
|
|
75
127
|
If full text is unavailable, record `full_text_unavailable`. Use only the preview for hook analysis and do not infer missing body details.
|
|
76
128
|
|
|
129
|
+
## Opening Preview Measurement
|
|
130
|
+
|
|
131
|
+
Measure the visible opening for every shortlisted source post before extracting
|
|
132
|
+
the hook pattern. This makes the study useful for LinkedIn, not just generally
|
|
133
|
+
"good writing."
|
|
134
|
+
|
|
135
|
+
LinkedIn does not publish exact "see more" cutoff rules. Treat these as
|
|
136
|
+
conservative v1 planning budgets:
|
|
137
|
+
|
|
138
|
+
- `pass`: opening hook is <= 110 chars including newlines, every nonblank line
|
|
139
|
+
is <= 45 chars, and the hook's core point lands before likely truncation.
|
|
140
|
+
- `warn`: opening hook is 111-140 chars including newlines, any nonblank line is
|
|
141
|
+
46-55 chars, or blank lines create visual-line risk. Blank lines are allowed,
|
|
142
|
+
but they count as physical lines.
|
|
143
|
+
- `fail`: opening hook is > 140 chars including newlines, any nonblank line is
|
|
144
|
+
> 55 chars, or the hook's core point depends on text after likely truncation.
|
|
145
|
+
|
|
146
|
+
Desktop preview has more room, so record it separately, but never let desktop
|
|
147
|
+
fit compensate for a mobile `fail`.
|
|
148
|
+
|
|
149
|
+
For each source, record:
|
|
150
|
+
|
|
151
|
+
- `sourceTextBasis`: `full_text`, `search_preview`, or `manual_user_source`
|
|
152
|
+
- `openingTextUsed`
|
|
153
|
+
- `charCountIncludingNewlines`
|
|
154
|
+
- `physicalLineCount`
|
|
155
|
+
- `contentLineCount`
|
|
156
|
+
- `firstLineChars`
|
|
157
|
+
- `firstTwoPhysicalLinesChars`
|
|
158
|
+
- `firstTwoContentLinesChars`
|
|
159
|
+
- `longestNonblankLineChars`
|
|
160
|
+
- `blankLineCountBeforeFold`
|
|
161
|
+
- `mobilePreviewBudget`: `pass`, `warn`, or `fail`
|
|
162
|
+
- `desktopPreviewBudget`: `pass`, `warn`, or `fail`
|
|
163
|
+
- `blankLineVisualRisk`
|
|
164
|
+
- `corePointBeforeLikelyTruncation`
|
|
165
|
+
|
|
166
|
+
If only a search preview is available, do not pretend the opening is complete.
|
|
167
|
+
Record `sourceTextBasis: search_preview` and lower confidence when the hook
|
|
168
|
+
appears cut off or body context is unavailable.
|
|
169
|
+
|
|
77
170
|
## Hook Extraction
|
|
78
171
|
|
|
79
|
-
Extract structure, not
|
|
172
|
+
Extract structure and reusable language patterns, not copied prose. The goal is
|
|
173
|
+
to learn the exact kinds of words, phrase shapes, sentence rhythms, and body
|
|
174
|
+
moves that are working, then adapt them into the user's voice.
|
|
80
175
|
|
|
81
176
|
For each shortlisted source post, record:
|
|
82
177
|
|
|
83
178
|
- URL
|
|
84
179
|
- author
|
|
180
|
+
- author profile URL when available
|
|
85
181
|
- engagement totals and available likes/comments/shares breakdown
|
|
86
182
|
- creator repeat evidence
|
|
87
183
|
- visible hook text or preview
|
|
88
|
-
-
|
|
184
|
+
- opening preview measurement fields from the section above
|
|
89
185
|
- hook mechanism
|
|
186
|
+
- exact hook language patterns: reusable words, phrase shapes, contrast forms,
|
|
187
|
+
sentence shapes, and transition moves
|
|
90
188
|
- story mechanism when the post is a story
|
|
91
189
|
- internal question created
|
|
92
190
|
- emotional trigger
|
|
@@ -94,6 +192,81 @@ For each shortlisted source post, record:
|
|
|
94
192
|
- lead magnet or engagement bait penalty
|
|
95
193
|
- weighted signal notes
|
|
96
194
|
- replicability score
|
|
195
|
+
- track person recommendation: `yes`, `no`, or `ask_user`
|
|
196
|
+
- tracking reason when recommended
|
|
197
|
+
|
|
198
|
+
## Specific Language Extraction
|
|
199
|
+
|
|
200
|
+
For each keeper, extract the source's specific language mechanics in this
|
|
201
|
+
format:
|
|
202
|
+
|
|
203
|
+
```text
|
|
204
|
+
Phrase pattern:
|
|
205
|
+
"<phrase or phrase shape>"
|
|
206
|
+
|
|
207
|
+
Role:
|
|
208
|
+
<what the words do: create contrast, compress pain, name the enemy, make timing
|
|
209
|
+
the villain, move from surface action to system outcome, etc.>
|
|
210
|
+
|
|
211
|
+
Source:
|
|
212
|
+
<author + URL>
|
|
213
|
+
|
|
214
|
+
Reusable forms:
|
|
215
|
+
- <template form 1>
|
|
216
|
+
- <template form 2>
|
|
217
|
+
- <template form 3>
|
|
218
|
+
|
|
219
|
+
Adapted to user's idea:
|
|
220
|
+
- <new phrase in the user's voice>
|
|
221
|
+
|
|
222
|
+
Do not copy:
|
|
223
|
+
<words, proof, joke, or company context that belongs to the source>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Examples of the level of specificity required:
|
|
227
|
+
|
|
228
|
+
- "not because [obvious reason]. because [real reason]."
|
|
229
|
+
- "most teams stop at [surface step]."
|
|
230
|
+
- "the [thing] was [state]. you just never [saw/used/launched] it in time."
|
|
231
|
+
- "the maintenance is the tax."
|
|
232
|
+
- "[thing] does not fail in your head. it fails in the gap between [A] and [B]."
|
|
233
|
+
- "the important part is not that AI [surface action]. the important part is that [system outcome]."
|
|
234
|
+
- "one [constrained operator] can run the whole [machine] if [constraint]."
|
|
235
|
+
|
|
236
|
+
Never reduce this section to high-level labels like "contrarian" or
|
|
237
|
+
"founder story." Those labels are allowed only after the exact phrase mechanics
|
|
238
|
+
are captured.
|
|
239
|
+
|
|
240
|
+
## Body Structure Extraction
|
|
241
|
+
|
|
242
|
+
For each keeper with full text available, extract the body in this format:
|
|
243
|
+
|
|
244
|
+
```text
|
|
245
|
+
Body pattern:
|
|
246
|
+
<short name>
|
|
247
|
+
|
|
248
|
+
Source:
|
|
249
|
+
<author + URL>
|
|
250
|
+
|
|
251
|
+
Sequence:
|
|
252
|
+
1. <paragraph/job 1>
|
|
253
|
+
2. <paragraph/job 2>
|
|
254
|
+
3. <paragraph/job 3>
|
|
255
|
+
|
|
256
|
+
Exact language moves:
|
|
257
|
+
- "<phrase shape or transition>"
|
|
258
|
+
- "<sentence pattern>"
|
|
259
|
+
- "<closing move>"
|
|
260
|
+
|
|
261
|
+
Adapted body move:
|
|
262
|
+
<how this would show up in the user's post>
|
|
263
|
+
|
|
264
|
+
Replicability:
|
|
265
|
+
high | medium | low
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
If full text is unavailable, record `full_text_unavailable` and do not infer
|
|
269
|
+
body structure beyond the visible preview.
|
|
97
270
|
|
|
98
271
|
## Story Mechanism
|
|
99
272
|
|
|
@@ -124,3 +297,19 @@ Draft-ready output must block or retry when:
|
|
|
124
297
|
## Save Requirement
|
|
125
298
|
|
|
126
299
|
Save the research with `mcp__sellable__save_hook_research` before drafting.
|
|
300
|
+
|
|
301
|
+
The saved research must contain enough detail to support a user-visible
|
|
302
|
+
`Research Learning Report`: source examples, full adapted hook blocks, exact
|
|
303
|
+
phrase patterns, body structures, rejected examples, tracked-person
|
|
304
|
+
recommendations, and gold-standard recommendations.
|
|
305
|
+
|
|
306
|
+
If the user approves a creator/person as a recurring inspiration source, also
|
|
307
|
+
call `mcp__sellable__upsert_engage_tracked_person` with:
|
|
308
|
+
|
|
309
|
+
- `name`: display name
|
|
310
|
+
- `linkedinUrl`: canonical LinkedIn profile URL
|
|
311
|
+
- `reason`: concise lane and why they are worth tracking
|
|
312
|
+
|
|
313
|
+
Do not track a person only because one post was viral. Track them when they have
|
|
314
|
+
repeated strong posts, unusually high topic fit, or the user explicitly says
|
|
315
|
+
they like them.
|
|
@@ -59,6 +59,9 @@ Hook research files must preserve:
|
|
|
59
59
|
- author/profile URLs
|
|
60
60
|
- engagement totals
|
|
61
61
|
- full-text availability
|
|
62
|
+
- source hook preview measurements, including text basis, char count including
|
|
63
|
+
newlines, physical/content line counts, longest nonblank line, blank-line
|
|
64
|
+
visual risk, and mobile/desktop preview budget status
|
|
62
65
|
- extracted hook patterns
|
|
63
66
|
- selected hook basis
|
|
64
67
|
|
|
@@ -67,7 +70,8 @@ Draft files must preserve:
|
|
|
67
70
|
- source idea ID
|
|
68
71
|
- hook research ID
|
|
69
72
|
- draft body
|
|
70
|
-
- validation receipt
|
|
73
|
+
- validation receipt, including LinkedIn preview pass/warn/fail status and
|
|
74
|
+
compact fallback when the selected hook carries a warning
|
|
71
75
|
- status: `draft`, `ready`, or `needs_revision`
|
|
72
76
|
|
|
73
77
|
Published files must preserve:
|
|
@@ -32,7 +32,9 @@ Each candidate should include:
|
|
|
32
32
|
- hook text
|
|
33
33
|
- source pattern
|
|
34
34
|
- score
|
|
35
|
-
- char count and first-line / first-two-line preview measurements
|
|
35
|
+
- char count including newlines and first-line / first-two-line preview measurements
|
|
36
|
+
- physical line count, content line count, longest nonblank line, and blank-line risk
|
|
37
|
+
- `previewBudgetStatus`: `pass`, `warn`, or `fail`
|
|
36
38
|
- mobile and desktop preview fit
|
|
37
39
|
- proof/story dependency
|
|
38
40
|
- AI-tell risk
|
|
@@ -52,25 +54,44 @@ After the first draft:
|
|
|
52
54
|
|
|
53
55
|
## LinkedIn Preview Audit
|
|
54
56
|
|
|
55
|
-
Audit the selected hook and top candidates against conservative LinkedIn
|
|
57
|
+
Audit the selected hook and top candidates against conservative LinkedIn
|
|
58
|
+
preview budgets. LinkedIn does not publish exact "see more" cutoff rules, and
|
|
59
|
+
rendering varies by device, app version, font, media, and line break. This audit
|
|
60
|
+
is a mobile-first safety gate, not a claim about an official LinkedIn limit.
|
|
56
61
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
62
|
+
Use:
|
|
63
|
+
|
|
64
|
+
- `pass`: hook is <= 110 chars including newlines, every nonblank line is <= 45 chars, and the hook's core point lands before likely truncation.
|
|
65
|
+
- `warn`: hook is 111-140 chars including newlines, any nonblank line is 46-55 chars, or blank lines create visual-line risk. Blank lines are allowed, but they count as physical lines.
|
|
66
|
+
- `fail`: hook is > 140 chars including newlines, any nonblank line is > 55 chars, or the hook's point depends on text after likely truncation.
|
|
67
|
+
|
|
68
|
+
Desktop preview usually has more room. Still record desktop fit, but never let
|
|
69
|
+
desktop fit compensate for a mobile `fail`.
|
|
61
70
|
|
|
62
71
|
Record:
|
|
63
72
|
|
|
64
73
|
- `charCount`
|
|
74
|
+
- `charCountIncludingNewlines`
|
|
65
75
|
- `firstLineChars`
|
|
66
76
|
- `firstTwoLinesChars`
|
|
77
|
+
- `physicalLineCount`
|
|
78
|
+
- `contentLineCount`
|
|
79
|
+
- `longestNonblankLineChars`
|
|
80
|
+
- `blankLineCountBeforeFold`
|
|
81
|
+
- `blankLineVisualRisk`
|
|
82
|
+
- `corePointBeforeLikelyTruncation`
|
|
83
|
+
- `previewBudgetStatus`
|
|
67
84
|
- `mobilePreviewFit`
|
|
68
85
|
- `desktopPreviewFit`
|
|
69
86
|
- `lineCountEstimate`
|
|
70
87
|
- `truncationRisk`
|
|
71
88
|
- `rewriteIfTruncated`
|
|
89
|
+
- `compactFallback` when `previewBudgetStatus` is `warn`
|
|
72
90
|
|
|
73
|
-
|
|
91
|
+
If the hook only works after likely truncation, rewrite it. A draft cannot be
|
|
92
|
+
`ready` with `previewBudgetStatus: fail`. A draft may be `ready` with
|
|
93
|
+
`previewBudgetStatus: warn` only when the warning is explicit, usually because
|
|
94
|
+
the user prefers blank-line rhythm, and the receipt includes a compact fallback.
|
|
74
95
|
|
|
75
96
|
## Simplifier / Concrete-Language Audit
|
|
76
97
|
|
|
@@ -45,6 +45,11 @@ message assets through Sellable MCP tools:
|
|
|
45
45
|
After candidate generation and revision, and before returning `ready`, load
|
|
46
46
|
`create-campaign-v2-validation` through Sellable MCP as the final gate.
|
|
47
47
|
|
|
48
|
+
Both live and dry runs must produce or validate `message-validation.md` with
|
|
49
|
+
the same quality gates. The selected winner must pass the `Concrete Language Audit`:
|
|
50
|
+
identify and replace or cut abstract verbs, abstract nouns, abstract adjectives,
|
|
51
|
+
abstract adverbs, and cliches before the message is treated as ready.
|
|
52
|
+
|
|
48
53
|
Never reconstruct that branch from `brief.md`, `lead-review.md`,
|
|
49
54
|
`lead-sample.json`, `lead-filter.md`, `message-validation.md`, local files, or
|
|
50
55
|
direct database reads. If any required message asset cannot be loaded through MCP
|