@sellable/mcp 0.1.259 → 0.1.261
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/index-dev.js +0 -0
- package/dist/index.js +0 -0
- package/dist/tools/engage-discovery.d.ts +24 -0
- package/dist/tools/engage-discovery.js +114 -9
- package/dist/tools/registry.d.ts +8 -0
- package/package.json +1 -1
- package/skills/create-post/SKILL.md +334 -5
- package/skills/create-post/references/hook-research-playbook.md +269 -5
- package/skills/create-post/references/linkedin-preview-rendering.md +176 -0
- package/skills/create-post/references/post-file-contract.md +17 -0
- package/skills/create-post/references/post-validation.md +177 -8
- package/skills/create-post/references/premise-development.md +256 -5
- package/skills/research/config.json +9 -0
package/dist/index-dev.js
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
File without changes
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
type FollowerBandFit = "in_target_band" | "below_target_band" | "above_target_band" | "unknown";
|
|
2
|
+
type ReachSignals = {
|
|
3
|
+
targetFollowerMin?: number;
|
|
4
|
+
targetFollowerMax?: number;
|
|
5
|
+
followerBandFit: FollowerBandFit;
|
|
6
|
+
engagementPer1kFollowers: number | null;
|
|
7
|
+
weightedEngagementPer1kFollowers: number | null;
|
|
8
|
+
reachPenaltyMultiplier: number;
|
|
9
|
+
reachAdjustedScore: number;
|
|
10
|
+
confidence: "high" | "medium" | "low";
|
|
11
|
+
};
|
|
1
12
|
export type EngagementPost = {
|
|
2
13
|
postId: string;
|
|
3
14
|
url: string;
|
|
@@ -7,6 +18,7 @@ export type EngagementPost = {
|
|
|
7
18
|
name: string;
|
|
8
19
|
headline: string;
|
|
9
20
|
profileUrl: string;
|
|
21
|
+
followerCount?: number;
|
|
10
22
|
};
|
|
11
23
|
engagement: {
|
|
12
24
|
likes: number;
|
|
@@ -14,6 +26,7 @@ export type EngagementPost = {
|
|
|
14
26
|
shares: number;
|
|
15
27
|
total: number;
|
|
16
28
|
};
|
|
29
|
+
reachSignals?: ReachSignals;
|
|
17
30
|
contentPreview: string;
|
|
18
31
|
};
|
|
19
32
|
export type SearchEngagementPostsInput = {
|
|
@@ -23,6 +36,8 @@ export type SearchEngagementPostsInput = {
|
|
|
23
36
|
minTotalEngagement?: number;
|
|
24
37
|
maxPosts?: number;
|
|
25
38
|
excludePostUrls?: string[];
|
|
39
|
+
targetFollowerMin?: number;
|
|
40
|
+
targetFollowerMax?: number;
|
|
26
41
|
};
|
|
27
42
|
export type SearchEngagementPostsResponse = {
|
|
28
43
|
success: boolean;
|
|
@@ -70,9 +85,18 @@ export declare const engageDiscoveryToolDefinitions: {
|
|
|
70
85
|
};
|
|
71
86
|
description: string;
|
|
72
87
|
};
|
|
88
|
+
targetFollowerMin: {
|
|
89
|
+
type: string;
|
|
90
|
+
description: string;
|
|
91
|
+
};
|
|
92
|
+
targetFollowerMax: {
|
|
93
|
+
type: string;
|
|
94
|
+
description: string;
|
|
95
|
+
};
|
|
73
96
|
};
|
|
74
97
|
required: string[];
|
|
75
98
|
additionalProperties: boolean;
|
|
76
99
|
};
|
|
77
100
|
}[];
|
|
78
101
|
export declare function searchEngagementPosts(input: SearchEngagementPostsInput): Promise<SearchEngagementPostsResponse>;
|
|
102
|
+
export {};
|
|
@@ -32,6 +32,14 @@ export const engageDiscoveryToolDefinitions = [
|
|
|
32
32
|
items: { type: "string" },
|
|
33
33
|
description: "Optional list of post URLs to exclude (e.g. already engaged/scheduled).",
|
|
34
34
|
},
|
|
35
|
+
targetFollowerMin: {
|
|
36
|
+
type: "number",
|
|
37
|
+
description: "Optional lower bound for creator follower count when reach-normalizing hook/source quality.",
|
|
38
|
+
},
|
|
39
|
+
targetFollowerMax: {
|
|
40
|
+
type: "number",
|
|
41
|
+
description: "Optional upper bound for creator follower count when reach-normalizing hook/source quality.",
|
|
42
|
+
},
|
|
35
43
|
},
|
|
36
44
|
required: ["keywords"],
|
|
37
45
|
additionalProperties: false,
|
|
@@ -63,6 +71,79 @@ function safeNumber(value) {
|
|
|
63
71
|
const n = typeof value === "number" ? value : Number(value);
|
|
64
72
|
return Number.isFinite(n) ? n : 0;
|
|
65
73
|
}
|
|
74
|
+
function round3(value) {
|
|
75
|
+
return Number(value.toFixed(3));
|
|
76
|
+
}
|
|
77
|
+
function parseFollowerCount(author) {
|
|
78
|
+
const direct = safeNumber(author?.followerCount);
|
|
79
|
+
if (direct > 0)
|
|
80
|
+
return direct;
|
|
81
|
+
const text = String(author?.followers || author?.followerCountText || "");
|
|
82
|
+
const match = text.match(/([\d,.]+)\s*([kKmM])?/);
|
|
83
|
+
if (!match)
|
|
84
|
+
return undefined;
|
|
85
|
+
const base = Number(match[1].replace(/,/g, ""));
|
|
86
|
+
if (!Number.isFinite(base) || base <= 0)
|
|
87
|
+
return undefined;
|
|
88
|
+
const suffix = match[2]?.toLowerCase();
|
|
89
|
+
if (suffix === "m")
|
|
90
|
+
return Math.round(base * 1_000_000);
|
|
91
|
+
if (suffix === "k")
|
|
92
|
+
return Math.round(base * 1_000);
|
|
93
|
+
return Math.round(base);
|
|
94
|
+
}
|
|
95
|
+
function reachPenaltyMultiplier(followerCount, targetFollowerMin, targetFollowerMax) {
|
|
96
|
+
if (!followerCount || !targetFollowerMin || !targetFollowerMax)
|
|
97
|
+
return 0.4;
|
|
98
|
+
if (followerCount >= targetFollowerMin && followerCount <= targetFollowerMax) {
|
|
99
|
+
return 1;
|
|
100
|
+
}
|
|
101
|
+
if (followerCount < targetFollowerMin)
|
|
102
|
+
return 0.75;
|
|
103
|
+
if (followerCount <= targetFollowerMax * 2)
|
|
104
|
+
return 0.65;
|
|
105
|
+
if (followerCount <= targetFollowerMax * 5)
|
|
106
|
+
return 0.35;
|
|
107
|
+
return 0.15;
|
|
108
|
+
}
|
|
109
|
+
function followerBandFit(followerCount, targetFollowerMin, targetFollowerMax) {
|
|
110
|
+
if (!followerCount || !targetFollowerMin || !targetFollowerMax) {
|
|
111
|
+
return "unknown";
|
|
112
|
+
}
|
|
113
|
+
if (followerCount >= targetFollowerMin && followerCount <= targetFollowerMax) {
|
|
114
|
+
return "in_target_band";
|
|
115
|
+
}
|
|
116
|
+
if (followerCount < targetFollowerMin)
|
|
117
|
+
return "below_target_band";
|
|
118
|
+
return "above_target_band";
|
|
119
|
+
}
|
|
120
|
+
function buildReachSignals(params) {
|
|
121
|
+
const { followerCount, likes, comments, shares, total } = params;
|
|
122
|
+
const hasTarget = Boolean(params.targetFollowerMin && params.targetFollowerMax);
|
|
123
|
+
if (!hasTarget && !followerCount)
|
|
124
|
+
return undefined;
|
|
125
|
+
const weightedEngagement = likes + comments * 4 + shares * 12;
|
|
126
|
+
const penalty = reachPenaltyMultiplier(followerCount, params.targetFollowerMin, params.targetFollowerMax);
|
|
127
|
+
const engagementPer1kFollowers = followerCount
|
|
128
|
+
? round3((total / followerCount) * 1000)
|
|
129
|
+
: null;
|
|
130
|
+
const weightedEngagementPer1kFollowers = followerCount
|
|
131
|
+
? round3((weightedEngagement / followerCount) * 1000)
|
|
132
|
+
: null;
|
|
133
|
+
const reachAdjustedScore = weightedEngagementPer1kFollowers === null
|
|
134
|
+
? 0
|
|
135
|
+
: round3(weightedEngagementPer1kFollowers * penalty);
|
|
136
|
+
return {
|
|
137
|
+
targetFollowerMin: params.targetFollowerMin,
|
|
138
|
+
targetFollowerMax: params.targetFollowerMax,
|
|
139
|
+
followerBandFit: followerBandFit(followerCount, params.targetFollowerMin, params.targetFollowerMax),
|
|
140
|
+
engagementPer1kFollowers,
|
|
141
|
+
weightedEngagementPer1kFollowers,
|
|
142
|
+
reachPenaltyMultiplier: penalty,
|
|
143
|
+
reachAdjustedScore,
|
|
144
|
+
confidence: followerCount ? (hasTarget ? "high" : "medium") : "low",
|
|
145
|
+
};
|
|
146
|
+
}
|
|
66
147
|
export async function searchEngagementPosts(input) {
|
|
67
148
|
const api = getApi();
|
|
68
149
|
const keywords = (input.keywords || [])
|
|
@@ -79,6 +160,12 @@ export async function searchEngagementPosts(input) {
|
|
|
79
160
|
const maxPosts = typeof input.maxPosts === "number" && input.maxPosts > 0
|
|
80
161
|
? Math.min(50, input.maxPosts)
|
|
81
162
|
: 25;
|
|
163
|
+
const targetFollowerMin = typeof input.targetFollowerMin === "number" && input.targetFollowerMin > 0
|
|
164
|
+
? input.targetFollowerMin
|
|
165
|
+
: undefined;
|
|
166
|
+
const targetFollowerMax = typeof input.targetFollowerMax === "number" && input.targetFollowerMax > 0
|
|
167
|
+
? input.targetFollowerMax
|
|
168
|
+
: undefined;
|
|
82
169
|
const exclude = new Set((input.excludePostUrls || [])
|
|
83
170
|
.map((u) => normalizePostUrl(u))
|
|
84
171
|
.filter(Boolean));
|
|
@@ -87,10 +174,10 @@ export async function searchEngagementPosts(input) {
|
|
|
87
174
|
keywords: keywords.map((keyword) => ({ keyword })),
|
|
88
175
|
page,
|
|
89
176
|
});
|
|
90
|
-
const rawPosts = Array.isArray(response?.
|
|
91
|
-
? response.
|
|
92
|
-
: Array.isArray(response?.
|
|
93
|
-
? response.
|
|
177
|
+
const rawPosts = Array.isArray(response?.posts)
|
|
178
|
+
? response.posts
|
|
179
|
+
: Array.isArray(response?.topPostsForLLM)
|
|
180
|
+
? response.topPostsForLLM
|
|
94
181
|
: [];
|
|
95
182
|
const now = Date.now();
|
|
96
183
|
const oldestMs = now - maxAgeDays * 24 * 60 * 60 * 1000;
|
|
@@ -121,6 +208,16 @@ export async function searchEngagementPosts(input) {
|
|
|
121
208
|
tooOld += 1;
|
|
122
209
|
continue;
|
|
123
210
|
}
|
|
211
|
+
const followerCount = parseFollowerCount(p?.author);
|
|
212
|
+
const reachSignals = buildReachSignals({
|
|
213
|
+
followerCount,
|
|
214
|
+
likes,
|
|
215
|
+
comments,
|
|
216
|
+
shares,
|
|
217
|
+
total,
|
|
218
|
+
targetFollowerMin,
|
|
219
|
+
targetFollowerMax,
|
|
220
|
+
});
|
|
124
221
|
kept.push({
|
|
125
222
|
postId: String(p?.id || ""),
|
|
126
223
|
url,
|
|
@@ -132,18 +229,26 @@ export async function searchEngagementPosts(input) {
|
|
|
132
229
|
name: String(p?.author?.name || ""),
|
|
133
230
|
headline: String(p?.author?.headline || ""),
|
|
134
231
|
profileUrl: String(p?.author?.profileUrl || ""),
|
|
232
|
+
...(followerCount ? { followerCount } : {}),
|
|
135
233
|
},
|
|
136
234
|
engagement: { likes, comments, shares, total },
|
|
235
|
+
...(reachSignals ? { reachSignals } : {}),
|
|
137
236
|
contentPreview: previewText(String(p?.content || ""), 220),
|
|
138
237
|
});
|
|
139
|
-
if (kept.length >= maxPosts)
|
|
140
|
-
break;
|
|
141
238
|
}
|
|
142
|
-
|
|
143
|
-
kept.sort((a, b) =>
|
|
239
|
+
const hasReachTarget = Boolean(targetFollowerMin && targetFollowerMax);
|
|
240
|
+
kept.sort((a, b) => {
|
|
241
|
+
if (hasReachTarget) {
|
|
242
|
+
const reachDelta = (b.reachSignals?.reachAdjustedScore || 0) -
|
|
243
|
+
(a.reachSignals?.reachAdjustedScore || 0);
|
|
244
|
+
if (reachDelta !== 0)
|
|
245
|
+
return reachDelta;
|
|
246
|
+
}
|
|
247
|
+
return b.engagement.total - a.engagement.total;
|
|
248
|
+
});
|
|
144
249
|
return {
|
|
145
250
|
success: true,
|
|
146
|
-
posts: kept,
|
|
251
|
+
posts: kept.slice(0, maxPosts),
|
|
147
252
|
totalReturned: rawPosts.length,
|
|
148
253
|
filteredOut: { tooOld, excluded, tooLowEngagement },
|
|
149
254
|
};
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -1749,6 +1749,14 @@ export declare const allTools: ({
|
|
|
1749
1749
|
};
|
|
1750
1750
|
description: string;
|
|
1751
1751
|
};
|
|
1752
|
+
targetFollowerMin: {
|
|
1753
|
+
type: string;
|
|
1754
|
+
description: string;
|
|
1755
|
+
};
|
|
1756
|
+
targetFollowerMax: {
|
|
1757
|
+
type: string;
|
|
1758
|
+
description: string;
|
|
1759
|
+
};
|
|
1752
1760
|
};
|
|
1753
1761
|
required: string[];
|
|
1754
1762
|
additionalProperties: boolean;
|
package/package.json
CHANGED
|
@@ -84,6 +84,7 @@ Before drafting, load all required assets with `mcp__sellable__get_subskill_asse
|
|
|
84
84
|
3. `subskillName: "create-post", assetPath: "references/premise-development.md"`
|
|
85
85
|
4. `subskillName: "create-post", assetPath: "references/post-validation.md"`
|
|
86
86
|
5. `subskillName: "create-post", assetPath: "references/gold-standard-post-pack.md"`
|
|
87
|
+
6. `subskillName: "create-post", assetPath: "references/linkedin-preview-rendering.md"`
|
|
87
88
|
|
|
88
89
|
If any required asset is missing, unreadable, truncated without continuation, or internally inconsistent, return:
|
|
89
90
|
|
|
@@ -283,6 +284,173 @@ Space benchmark research:
|
|
|
283
284
|
7. For each approved tracked person, call `mcp__sellable__upsert_engage_tracked_person`.
|
|
284
285
|
|
|
285
286
|
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.
|
|
287
|
+
|
|
288
|
+
## Visible Whole-Flow Debug Mode
|
|
289
|
+
|
|
290
|
+
Use when the user asks to see the whole flow, run the flow step by step,
|
|
291
|
+
validate that the workflow is working, debug a bad output, explain why a draft
|
|
292
|
+
is bad, or otherwise asks for the process to be explicit.
|
|
293
|
+
|
|
294
|
+
This mode exists because a validation receipt hidden inside a saved draft is not
|
|
295
|
+
enough. The user must be able to inspect the reasoning path before the system
|
|
296
|
+
claims the workflow worked.
|
|
297
|
+
|
|
298
|
+
In visible whole-flow debug mode:
|
|
299
|
+
|
|
300
|
+
1. Run the normal create-post workflow.
|
|
301
|
+
2. Show a `Visible Flow Trace` with every checkpoint below.
|
|
302
|
+
3. Mark each checkpoint `pass`, `weak`, `fail`, or `blocked`.
|
|
303
|
+
4. Include the concrete output from that checkpoint, not only a label.
|
|
304
|
+
5. If any checkpoint is weak or failed, name the exact quality break and the
|
|
305
|
+
downstream effect on the draft.
|
|
306
|
+
6. Do not call the run successful just because files were saved.
|
|
307
|
+
7. Do not hide premise cards, source-template selection, hook candidates,
|
|
308
|
+
pre-draft structure, body-expression candidates, or validation findings only
|
|
309
|
+
inside the saved artifact.
|
|
310
|
+
|
|
311
|
+
The trace must use this order:
|
|
312
|
+
|
|
313
|
+
```text
|
|
314
|
+
Visible Flow Trace
|
|
315
|
+
|
|
316
|
+
0. Bootstrap
|
|
317
|
+
- auth/workspace:
|
|
318
|
+
- canonical prompt loaded:
|
|
319
|
+
- required assets loaded:
|
|
320
|
+
- memory loaded:
|
|
321
|
+
- package/version notes:
|
|
322
|
+
|
|
323
|
+
1. Raw Idea Capture
|
|
324
|
+
- idea id:
|
|
325
|
+
- raw source preserved:
|
|
326
|
+
- distilled brief:
|
|
327
|
+
- claims added or avoided:
|
|
328
|
+
|
|
329
|
+
2. Research Search Log
|
|
330
|
+
- search window:
|
|
331
|
+
- keywords:
|
|
332
|
+
- result count:
|
|
333
|
+
- full-text fetches:
|
|
334
|
+
- search gaps:
|
|
335
|
+
|
|
336
|
+
3. Weighted Source Selection
|
|
337
|
+
- kept sources:
|
|
338
|
+
- rejected sources:
|
|
339
|
+
- keeper scores:
|
|
340
|
+
- lead-magnet / engagement-bait penalties:
|
|
341
|
+
- why the top source actually fits:
|
|
342
|
+
|
|
343
|
+
4. Hook Autopsies
|
|
344
|
+
- source hook:
|
|
345
|
+
- rendered/mobile preview or preview-basis:
|
|
346
|
+
- see-more tension:
|
|
347
|
+
- curiosity debt:
|
|
348
|
+
- body promise:
|
|
349
|
+
- why it works:
|
|
350
|
+
- why it may not transfer:
|
|
351
|
+
|
|
352
|
+
5. Post Positioning Breakdowns
|
|
353
|
+
- source:
|
|
354
|
+
- positioning sequence:
|
|
355
|
+
- line-level narrative techniques:
|
|
356
|
+
- reusable template lines:
|
|
357
|
+
- adaptation guards:
|
|
358
|
+
|
|
359
|
+
6. Viral-Post Outlines
|
|
360
|
+
- source template:
|
|
361
|
+
- hook job:
|
|
362
|
+
- see-more trigger:
|
|
363
|
+
- beat sequence:
|
|
364
|
+
- body payoff:
|
|
365
|
+
- close job:
|
|
366
|
+
|
|
367
|
+
7. Market Belief Map
|
|
368
|
+
- resonating ideas:
|
|
369
|
+
- implicit beliefs:
|
|
370
|
+
- wants / resentments / fears:
|
|
371
|
+
- selected controversy:
|
|
372
|
+
- why this user can credibly say it:
|
|
373
|
+
- what not to claim:
|
|
374
|
+
|
|
375
|
+
8. Premise Cards
|
|
376
|
+
- 3-5 cards:
|
|
377
|
+
- story/scene:
|
|
378
|
+
- tension:
|
|
379
|
+
- reader value:
|
|
380
|
+
- proof available:
|
|
381
|
+
- proof missing:
|
|
382
|
+
- source-template fit:
|
|
383
|
+
- score:
|
|
384
|
+
- selected premise:
|
|
385
|
+
|
|
386
|
+
9. Source Template Selection
|
|
387
|
+
- selected template:
|
|
388
|
+
- positioning sequence to borrow:
|
|
389
|
+
- hook move to borrow:
|
|
390
|
+
- body outline to borrow:
|
|
391
|
+
- required user proof:
|
|
392
|
+
- forbidden borrowing:
|
|
393
|
+
- no-template rationale if rejected:
|
|
394
|
+
|
|
395
|
+
10. Hook Lab
|
|
396
|
+
- at least 12 hooks:
|
|
397
|
+
- rendered preview record or explicit preview-basis:
|
|
398
|
+
- hook-to-body promise:
|
|
399
|
+
- score:
|
|
400
|
+
- selected hook:
|
|
401
|
+
- rejected winning-looking hooks and why:
|
|
402
|
+
|
|
403
|
+
11. Pre-Draft Narrative Outline
|
|
404
|
+
- hierarchical outline shown before draft:
|
|
405
|
+
- I. hook and click debt:
|
|
406
|
+
- II. thesis the post will defend:
|
|
407
|
+
- III. operating model:
|
|
408
|
+
- IV. body shape borrowed from posts that worked:
|
|
409
|
+
- V. narrative beats:
|
|
410
|
+
- VI. scan path and proof safety:
|
|
411
|
+
- user corrections applied before prose:
|
|
412
|
+
|
|
413
|
+
12. Body Expression Lab
|
|
414
|
+
- 5-8 body-expression candidates:
|
|
415
|
+
- best lines:
|
|
416
|
+
- weak lines:
|
|
417
|
+
- hook promise repayment:
|
|
418
|
+
- proof risk:
|
|
419
|
+
- score:
|
|
420
|
+
- combined body plan:
|
|
421
|
+
|
|
422
|
+
13. Draft
|
|
423
|
+
- draft body:
|
|
424
|
+
- lines intentionally copied from user source:
|
|
425
|
+
- outside-source wording copied: yes/no:
|
|
426
|
+
- known weak lines:
|
|
427
|
+
|
|
428
|
+
14. Validation And Save
|
|
429
|
+
- ready status:
|
|
430
|
+
- proof gate:
|
|
431
|
+
- voice gate:
|
|
432
|
+
- anti-AI gate:
|
|
433
|
+
- mobile preview gate:
|
|
434
|
+
- template adaptation gate:
|
|
435
|
+
- hook-to-body repayment:
|
|
436
|
+
- quality break, if any:
|
|
437
|
+
- saved idea path:
|
|
438
|
+
- saved research path:
|
|
439
|
+
- saved draft path:
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Quality-break rules:
|
|
443
|
+
|
|
444
|
+
- If the draft is bad, say which checkpoint produced the bad draft. For example:
|
|
445
|
+
weak raw story, wrong selected source template, hook promise not repaid,
|
|
446
|
+
body expression lab too generic, proof missing, or voice mismatch.
|
|
447
|
+
- A draft with a coherent validation receipt but poor body copy is not a
|
|
448
|
+
successful run. Mark it `needs_revision` and show the checkpoint where the
|
|
449
|
+
body lost the premise.
|
|
450
|
+
- If the source idea is too abstract, stop at premise development or save a
|
|
451
|
+
`needs_revision` draft only after showing the missing story/proof.
|
|
452
|
+
- If the user is judging the workflow itself, prefer showing the trace over
|
|
453
|
+
optimizing for a polished final post.
|
|
286
454
|
</modes>
|
|
287
455
|
|
|
288
456
|
<pipeline>
|
|
@@ -320,6 +488,12 @@ The research worker must return a compact packet only:
|
|
|
320
488
|
- market belief map: resonating ideas, implicit beliefs, audience wants, resentments, fears, and credible controversy angles
|
|
321
489
|
- premise inputs: real scenes, observed tensions, reader value openings, and proof gaps
|
|
322
490
|
- exact phrase patterns and sentence shapes
|
|
491
|
+
- post positioning breakdowns that label each meaningful line or phrase by
|
|
492
|
+
narrative job and category
|
|
493
|
+
- viral-post outlines for the best source posts
|
|
494
|
+
- line-to-template conversions that turn source structures into reusable
|
|
495
|
+
templates without source wording
|
|
496
|
+
- hook-to-body promise maps that show how each hook tells the body
|
|
323
497
|
- body structures and exact body language moves
|
|
324
498
|
- preview measurements
|
|
325
499
|
- track-person and gold-standard recommendations
|
|
@@ -343,7 +517,15 @@ Default flow:
|
|
|
343
517
|
10. For story posts, extract the story mechanism that made the post work, not just the first line.
|
|
344
518
|
11. Extract hook structures plus specific reusable words, phrases, sentence
|
|
345
519
|
shapes, transitions, and body language patterns.
|
|
346
|
-
12.
|
|
520
|
+
12. Create a post positioning breakdown for each keeper post: line/phrase,
|
|
521
|
+
category, narrative technique, tension created, reader question opened,
|
|
522
|
+
proof dependency, and reusable template line.
|
|
523
|
+
13. Convert each keeper into a viral-post outline: hook job, see-more trigger,
|
|
524
|
+
body payoff, close job, and beat-by-beat narrative structure.
|
|
525
|
+
14. Convert the best outlines into reusable post templates with positioning
|
|
526
|
+
sequences, required story/proof inputs, forbidden borrowing, and
|
|
527
|
+
Sellable-specific adaptation instructions.
|
|
528
|
+
15. Save the research with `mcp__sellable__save_hook_research`.
|
|
347
529
|
|
|
348
530
|
Record provenance:
|
|
349
531
|
|
|
@@ -362,6 +544,10 @@ Record provenance:
|
|
|
362
544
|
- market belief map and selected controversy
|
|
363
545
|
- premise cards and selected premise
|
|
364
546
|
- exact phrase patterns and sentence shapes
|
|
547
|
+
- post positioning breakdowns
|
|
548
|
+
- viral-post outlines
|
|
549
|
+
- reusable post templates
|
|
550
|
+
- hook-to-body promise maps
|
|
365
551
|
- body structures and body language patterns
|
|
366
552
|
- why each pattern fits the user's idea and voice
|
|
367
553
|
|
|
@@ -410,7 +596,10 @@ Hook patterns learned:
|
|
|
410
596
|
1. full adapted hook block
|
|
411
597
|
- source mechanism:
|
|
412
598
|
- preview budget:
|
|
599
|
+
- see-more tension:
|
|
600
|
+
- curiosity debt:
|
|
413
601
|
- internal question:
|
|
602
|
+
- hook-to-body promise:
|
|
414
603
|
- why it fits / why it does not:
|
|
415
604
|
|
|
416
605
|
Specific words and phrase shapes:
|
|
@@ -421,9 +610,35 @@ Specific words and phrase shapes:
|
|
|
421
610
|
- adapted Sellable form:
|
|
422
611
|
- do not copy:
|
|
423
612
|
|
|
613
|
+
Post positioning breakdown templates:
|
|
614
|
+
1. source + template name
|
|
615
|
+
- positioning sequence:
|
|
616
|
+
- line-level narrative techniques:
|
|
617
|
+
- tension created:
|
|
618
|
+
- reader questions opened:
|
|
619
|
+
- reusable template lines:
|
|
620
|
+
- Sellable adaptation:
|
|
621
|
+
|
|
622
|
+
Viral-post outlines:
|
|
623
|
+
1. outline name
|
|
624
|
+
- hook job:
|
|
625
|
+
- see-more trigger:
|
|
626
|
+
- body payoff:
|
|
627
|
+
- close job:
|
|
628
|
+
- beat sequence:
|
|
629
|
+
|
|
630
|
+
Line-to-template conversion:
|
|
631
|
+
1. source line/beat
|
|
632
|
+
- narrative job:
|
|
633
|
+
- template line shape:
|
|
634
|
+
- required user story/proof:
|
|
635
|
+
- forbidden borrowing:
|
|
636
|
+
- adapted Sellable expression:
|
|
637
|
+
|
|
424
638
|
Body structures learned:
|
|
425
639
|
1. structure name
|
|
426
640
|
- source:
|
|
641
|
+
- positioning sequence:
|
|
427
642
|
- sequence:
|
|
428
643
|
- exact language moves:
|
|
429
644
|
- adapted Sellable body move:
|
|
@@ -437,9 +652,9 @@ Save recommendations:
|
|
|
437
652
|
- gold-standard candidates:
|
|
438
653
|
|
|
439
654
|
Recommended draft directions:
|
|
440
|
-
1. premise card + hook block + body structure
|
|
441
|
-
2. premise card + hook block + body structure
|
|
442
|
-
3. premise card + hook block + body structure
|
|
655
|
+
1. premise card + source template + hook block + viral outline + body structure
|
|
656
|
+
2. premise card + source template + hook block + viral outline + body structure
|
|
657
|
+
3. premise card + source template + hook block + viral outline + body structure
|
|
443
658
|
```
|
|
444
659
|
|
|
445
660
|
Keep this report concise enough to read, but concrete enough that another agent
|
|
@@ -453,7 +668,9 @@ Generate 3-5 `Premise Card` candidates from the raw idea, market research, core
|
|
|
453
668
|
memory, story/proof files, and current-session user feedback. Each card must
|
|
454
669
|
include a real story/scene or observed pattern, target reader, common belief,
|
|
455
670
|
contrarian truth, tension, reader value, proof available, proof missing, and a
|
|
456
|
-
score.
|
|
671
|
+
score. Each card must also evaluate which source template or no-template path
|
|
672
|
+
fits, which positioning sequence to test, and how the hook promise will be
|
|
673
|
+
repaid in the body.
|
|
457
674
|
|
|
458
675
|
Select the strongest premise before hook generation. The selected premise must
|
|
459
676
|
pass:
|
|
@@ -465,12 +682,103 @@ pass:
|
|
|
465
682
|
- `credible_speaker`
|
|
466
683
|
- `proof_safety`
|
|
467
684
|
- `market_heat`
|
|
685
|
+
- `template_fit`
|
|
686
|
+
- `hook_to_body_repayment`
|
|
468
687
|
|
|
469
688
|
If the idea has market heat but no real scene, ask for the missing scene unless
|
|
470
689
|
the user explicitly requested an immediate draft. For immediate draft mode, use
|
|
471
690
|
only source-backed observed patterns and save the draft as `needs_revision`
|
|
472
691
|
unless the premise still has concrete reader value.
|
|
473
692
|
|
|
693
|
+
## Step 1.9: Pre-Draft Narrative Outline
|
|
694
|
+
|
|
695
|
+
Before generating final draft prose, create and show a compact `Pre-Draft
|
|
696
|
+
Narrative Outline`. This is not a checklist. It is the user-visible argument
|
|
697
|
+
skeleton that lets the user confirm what the post will say, in what order, and
|
|
698
|
+
which proven body shapes will guide the draft before the system writes body
|
|
699
|
+
copy.
|
|
700
|
+
|
|
701
|
+
The outline must be concise, mobile-scanable, and concrete enough for the user
|
|
702
|
+
to approve or correct. Do not hide it inside the validation receipt after the
|
|
703
|
+
draft. Show it before writing the draft body unless the user explicitly says to
|
|
704
|
+
skip outline/structure and write immediately. Even when the user skips the
|
|
705
|
+
visible checkpoint, still include the outline in the validation receipt.
|
|
706
|
+
|
|
707
|
+
The `Pre-Draft Narrative Outline` must use hierarchical outline notation:
|
|
708
|
+
Roman numerals for major narrative beats, letters for sub-beats, and lowercase
|
|
709
|
+
roman numerals for proof/examples/body moves. Do not replace this with a flat
|
|
710
|
+
field list.
|
|
711
|
+
|
|
712
|
+
The `Pre-Draft Narrative Outline` must include:
|
|
713
|
+
|
|
714
|
+
```text
|
|
715
|
+
Pre-Draft Narrative Outline
|
|
716
|
+
I. Hook and click debt
|
|
717
|
+
A. Selected hook:
|
|
718
|
+
B. Rendered mobile preview verdict:
|
|
719
|
+
C. What "see more" must repay:
|
|
720
|
+
|
|
721
|
+
II. Thesis the post will defend
|
|
722
|
+
A. One-sentence thesis:
|
|
723
|
+
B. Reader being taught:
|
|
724
|
+
C. Why this reader cares now:
|
|
725
|
+
|
|
726
|
+
III. Operating model
|
|
727
|
+
A. Core equation or mechanism:
|
|
728
|
+
B. Key definitions:
|
|
729
|
+
i. <term>: <plain definition + concrete examples>
|
|
730
|
+
ii. <term>: <plain definition + concrete examples>
|
|
731
|
+
|
|
732
|
+
IV. Body shape borrowed from posts that worked
|
|
733
|
+
A. Selected source template or no-template rationale:
|
|
734
|
+
B. Working body pattern(s) being adapted:
|
|
735
|
+
i. <pattern name>: <beat order and why it works>
|
|
736
|
+
ii. <pattern name>: <beat order and why it works>
|
|
737
|
+
C. What gets borrowed:
|
|
738
|
+
i. <narrative job, sequence, transition, or proof order>
|
|
739
|
+
D. What must not be copied:
|
|
740
|
+
i. <source wording, creator-specific proof, joke, or context>
|
|
741
|
+
|
|
742
|
+
V. Narrative beats
|
|
743
|
+
A. Beat 1: <job, reader state before/after, example/proof>
|
|
744
|
+
i. Line shape or section label:
|
|
745
|
+
ii. Concrete examples:
|
|
746
|
+
B. Beat 2: <job, reader state before/after, example/proof>
|
|
747
|
+
i. Line shape or section label:
|
|
748
|
+
ii. Concrete examples:
|
|
749
|
+
C. Beat 3: <job, reader state before/after, example/proof>
|
|
750
|
+
i. Line shape or section label:
|
|
751
|
+
ii. Concrete examples:
|
|
752
|
+
|
|
753
|
+
VI. Scan path and proof safety
|
|
754
|
+
A. Mobile scan path:
|
|
755
|
+
B. Proof claims:
|
|
756
|
+
i. <claim>: <source + public-safety status>
|
|
757
|
+
C. Abstractions to remove:
|
|
758
|
+
i. <abstract phrase> -> <concrete replacement>
|
|
759
|
+
D. Draft risks:
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
Rules:
|
|
763
|
+
|
|
764
|
+
- The hook must already have a rendered mobile and desktop preview record.
|
|
765
|
+
- The thesis must be one sentence the post can defend.
|
|
766
|
+
- The reader must be specific enough to guide what gets cut.
|
|
767
|
+
- `Body shape borrowed from posts that worked` must name the body pattern or
|
|
768
|
+
explain why no-template is stronger. It must say what narrative job is being
|
|
769
|
+
borrowed, not just "make it like this creator."
|
|
770
|
+
- `Narrative beats` must show the order of the argument with `I.`, `A.`, and
|
|
771
|
+
`i.`-style hierarchy. A flat checklist fails this step.
|
|
772
|
+
- Key definitions must name concrete examples when the post teaches an
|
|
773
|
+
operating concept. For example, define `lead source` as how the list was
|
|
774
|
+
built, not as a persona label.
|
|
775
|
+
- `mobile scan path` must say what a reader understands if they read only the
|
|
776
|
+
hook, separators, section labels, numbers, and final line.
|
|
777
|
+
- `abstractions to remove` must list abstract phrases and the concrete words
|
|
778
|
+
that will replace them.
|
|
779
|
+
- If the user corrects the outline, update the outline first, then draft. Do
|
|
780
|
+
not patch the final prose while leaving the outline stale.
|
|
781
|
+
|
|
474
782
|
## Step 2: Hook Candidates
|
|
475
783
|
|
|
476
784
|
Generate at least 12 hook candidates from the selected premise unless the user
|
|
@@ -528,7 +836,12 @@ Draft from:
|
|
|
528
836
|
- exact raw idea
|
|
529
837
|
- selected premise card
|
|
530
838
|
- selected hook
|
|
839
|
+
- approved or latest `Pre-Draft Narrative Outline`
|
|
531
840
|
- hook research artifact
|
|
841
|
+
- selected source template or no-template rationale
|
|
842
|
+
- viral-post outline
|
|
843
|
+
- post positioning breakdown template
|
|
844
|
+
- body expression candidates and combined body plan
|
|
532
845
|
- user's core memory
|
|
533
846
|
- story/proof files
|
|
534
847
|
- post writing rules
|
|
@@ -549,11 +862,20 @@ Every saved draft needs a validation receipt with:
|
|
|
549
862
|
- selected premise card
|
|
550
863
|
- candidate hooks considered
|
|
551
864
|
- selected hook and why
|
|
865
|
+
- pre-draft narrative outline
|
|
866
|
+
- selected source template and no-copy adaptation rationale
|
|
867
|
+
- post positioning breakdown
|
|
868
|
+
- viral-post outline
|
|
869
|
+
- hook-to-body promise map
|
|
870
|
+
- body expression candidates and combined body plan
|
|
552
871
|
- proof claims used and source
|
|
553
872
|
- story/proof files consulted
|
|
554
873
|
- gold standards consulted
|
|
555
874
|
- LinkedIn preview audit
|
|
556
875
|
- premise/value audit findings
|
|
876
|
+
- mobile scanability audit findings
|
|
877
|
+
- template-adaptation audit findings
|
|
878
|
+
- abstraction-to-concrete rewrite audit findings
|
|
557
879
|
- simplifier/concrete-language audit findings
|
|
558
880
|
- voice audit findings
|
|
559
881
|
- anti-AI audit findings
|
|
@@ -648,8 +970,15 @@ iteration:
|
|
|
648
970
|
score: <compact score object>
|
|
649
971
|
selected_premise: <premise or none>
|
|
650
972
|
selected_hook: <hook>
|
|
973
|
+
pre_draft_narrative_outline: <compact I/A/i outline summary or none>
|
|
974
|
+
selected_source_template: <template name/source or none>
|
|
975
|
+
visible_flow_trace: <required when user asked for whole-flow/debug/step-by-step mode; include checkpoint statuses and quality break>
|
|
651
976
|
validation_summary:
|
|
652
977
|
premise_value: pass | needs_user_input | needs_revision
|
|
978
|
+
mobile_scanability: pass | needs_revision
|
|
979
|
+
template_adaptation: pass | needs_revision | blocked
|
|
980
|
+
abstraction_to_concrete: pass | needs_revision
|
|
981
|
+
hook_to_body_repayment: pass | needs_revision
|
|
653
982
|
proof: pass | needs_user_input | blocked
|
|
654
983
|
voice: pass | needs_revision
|
|
655
984
|
anti_ai: pass | needs_revision
|