@sellable/mcp 0.1.0
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/.claude-plugin/plugin.json +12 -0
- package/.mcp.json +9 -0
- package/README.md +355 -0
- package/dist/api.d.ts +21 -0
- package/dist/api.js +73 -0
- package/dist/auth.d.ts +60 -0
- package/dist/auth.js +246 -0
- package/dist/engage-memory.d.ts +63 -0
- package/dist/engage-memory.js +354 -0
- package/dist/index-dev.d.ts +2 -0
- package/dist/index-dev.js +17 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +499 -0
- package/dist/skills.d.ts +11 -0
- package/dist/skills.js +97 -0
- package/dist/tools/auth.d.ts +30 -0
- package/dist/tools/auth.js +124 -0
- package/dist/tools/blueprint-commit.d.ts +174 -0
- package/dist/tools/blueprint-commit.js +286 -0
- package/dist/tools/bootstrap.d.ts +64 -0
- package/dist/tools/bootstrap.js +246 -0
- package/dist/tools/campaigns.d.ts +589 -0
- package/dist/tools/campaigns.js +892 -0
- package/dist/tools/cells.d.ts +58 -0
- package/dist/tools/cells.js +48 -0
- package/dist/tools/context.d.ts +88 -0
- package/dist/tools/context.js +271 -0
- package/dist/tools/csv-domains.d.ts +73 -0
- package/dist/tools/csv-domains.js +464 -0
- package/dist/tools/csv-linkedin.d.ts +102 -0
- package/dist/tools/csv-linkedin.js +712 -0
- package/dist/tools/direct-campaigns.d.ts +240 -0
- package/dist/tools/direct-campaigns.js +250 -0
- package/dist/tools/engage-bootstrap.d.ts +94 -0
- package/dist/tools/engage-bootstrap.js +205 -0
- package/dist/tools/engage-discovery.d.ts +78 -0
- package/dist/tools/engage-discovery.js +150 -0
- package/dist/tools/engage-memory.d.ts +181 -0
- package/dist/tools/engage-memory.js +143 -0
- package/dist/tools/engage-state.d.ts +72 -0
- package/dist/tools/engage-state.js +62 -0
- package/dist/tools/enrichment.d.ts +167 -0
- package/dist/tools/enrichment.js +174 -0
- package/dist/tools/flow-preflight.d.ts +68 -0
- package/dist/tools/flow-preflight.js +138 -0
- package/dist/tools/framework.d.ts +44 -0
- package/dist/tools/framework.js +153 -0
- package/dist/tools/interaction-mode.d.ts +27 -0
- package/dist/tools/interaction-mode.js +102 -0
- package/dist/tools/leads.d.ts +2417 -0
- package/dist/tools/leads.js +2307 -0
- package/dist/tools/linkedin.d.ts +210 -0
- package/dist/tools/linkedin.js +229 -0
- package/dist/tools/navigation.d.ts +91 -0
- package/dist/tools/navigation.js +381 -0
- package/dist/tools/one-off.d.ts +229 -0
- package/dist/tools/one-off.js +273 -0
- package/dist/tools/processing.d.ts +70 -0
- package/dist/tools/processing.js +56 -0
- package/dist/tools/prompts.d.ts +211 -0
- package/dist/tools/prompts.js +210 -0
- package/dist/tools/provider-preflight.d.ts +21 -0
- package/dist/tools/provider-preflight.js +59 -0
- package/dist/tools/readiness.d.ts +261 -0
- package/dist/tools/readiness.js +510 -0
- package/dist/tools/rows.d.ts +126 -0
- package/dist/tools/rows.js +105 -0
- package/dist/tools/rubrics.d.ts +497 -0
- package/dist/tools/rubrics.js +681 -0
- package/dist/tools/senders.d.ts +44 -0
- package/dist/tools/senders.js +69 -0
- package/dist/tools/sequencer.d.ts +127 -0
- package/dist/tools/sequencer.js +194 -0
- package/dist/tools/tables.d.ts +35 -0
- package/dist/tools/tables.js +36 -0
- package/dist/tools/verify-row.d.ts +36 -0
- package/dist/tools/verify-row.js +38 -0
- package/dist/tools/workspaces.d.ts +140 -0
- package/dist/tools/workspaces.js +139 -0
- package/dist/utils/workspace-root.d.ts +1 -0
- package/dist/utils/workspace-root.js +39 -0
- package/package.json +46 -0
- package/skills/building-gtm-tables/SKILL.md +216 -0
- package/skills/building-gtm-tables/core/auto-execute.yaml +19 -0
- package/skills/building-gtm-tables/core/blueprint-schema.json +72 -0
- package/skills/building-gtm-tables/references/brief-to-blueprint.md +334 -0
- package/skills/building-gtm-tables/references/column-type-catalog.md +318 -0
- package/skills/building-gtm-tables/references/common-blueprints.fixtures.ts +199 -0
- package/skills/building-gtm-tables/references/common-blueprints.md +44 -0
- package/skills/building-gtm-tables/references/failure-taxonomy.md +197 -0
- package/skills/building-gtm-tables/references/uat-seed-prompts.md +37 -0
- package/skills/building-gtm-tables/references/verify-loop.md +74 -0
- package/skills/campaign-messages/SKILL.md +173 -0
- package/skills/campaign-messages/flow.v1.json +75 -0
- package/skills/craft-message/SKILL.md +401 -0
- package/skills/create-campaign/ARCHITECTURE.md +232 -0
- package/skills/create-campaign/DISCUSS.md +296 -0
- package/skills/create-campaign/FLOW_ASCII.md +240 -0
- package/skills/create-campaign/HOST-PARITY-CHECKLIST.md +49 -0
- package/skills/create-campaign/README.md +142 -0
- package/skills/create-campaign/SKILL.md +286 -0
- package/skills/create-campaign/context/README.md +67 -0
- package/skills/create-campaign/context/_TEMPLATE.md +12 -0
- package/skills/create-campaign/context/context.md +35 -0
- package/skills/create-campaign/context/learnings.md +16 -0
- package/skills/create-campaign/context/registry.json +19 -0
- package/skills/create-campaign/core/flow.v1.json +217 -0
- package/skills/create-campaign/core/policy.md +191 -0
- package/skills/create-campaign/core/providers/apollo.json +35 -0
- package/skills/create-campaign/core/providers/prospeo.json +34 -0
- package/skills/create-campaign/core/providers/registry.json +31 -0
- package/skills/create-campaign/core/providers/sales-nav.json +37 -0
- package/skills/create-campaign/core/providers/signal-discovery.json +42 -0
- package/skills/create-campaign/references/brief-template.md +64 -0
- package/skills/create-campaign/references/campaign-quality.md +84 -0
- package/skills/create-campaign/references/copy-calibration-examples.md +120 -0
- package/skills/create-campaign/references/offer-patterns.md +108 -0
- package/skills/create-campaign/references/provider-selection-strategy.md +212 -0
- package/skills/create-campaign/references/question-examples.md +167 -0
- package/skills/create-campaign/references/token-fill-examples.md +81 -0
- package/skills/create-campaign-brief/ARCHITECTURE.md +72 -0
- package/skills/create-campaign-brief/DISCUSS.md +64 -0
- package/skills/create-campaign-brief/README.md +176 -0
- package/skills/create-campaign-brief/SKILL.md +537 -0
- package/skills/create-campaign-brief/references/brief-synthesis-rules.md +100 -0
- package/skills/create-campaign-brief/references/brief-template.md +220 -0
- package/skills/create-campaign-brief/references/campaign-idea-options.md +30 -0
- package/skills/create-campaign-brief/references/copy-appendix-template.md +62 -0
- package/skills/create-campaign-brief/references/draft-lifecycle.md +23 -0
- package/skills/create-campaign-brief/references/examples/MANIFEST.json +89 -0
- package/skills/create-campaign-brief/references/examples/briefs/clover.md +223 -0
- package/skills/create-campaign-brief/references/examples/briefs/galley.md +222 -0
- package/skills/create-campaign-brief/references/examples/briefs/gelee.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/hey-digital.md +234 -0
- package/skills/create-campaign-brief/references/examples/briefs/persona.md +231 -0
- package/skills/create-campaign-brief/references/examples/briefs/revvix.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/sellable-dev.md +220 -0
- package/skills/create-campaign-brief/references/examples/briefs/superposition.md +233 -0
- package/skills/create-campaign-brief/references/examples/briefs/superpower.md +219 -0
- package/skills/create-campaign-brief/references/examples/briefs/westpark-villas.md +220 -0
- package/skills/create-campaign-brief/references/icp-lock-question-bank.md +43 -0
- package/skills/create-campaign-brief/references/messaging-inputs.md +58 -0
- package/skills/create-campaign-brief/references/output-acceptance-rubric.md +62 -0
- package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +248 -0
- package/skills/create-campaign-brief/references/phase75-canonical-brief-template.md +319 -0
- package/skills/create-campaign-brief/references/phase75-good-brief-and-messaging-examples.md +445 -0
- package/skills/create-campaign-brief/references/quick-research-protocol.md +39 -0
- package/skills/create-campaign-brief/references/reference-sheet-protocol.md +60 -0
- package/skills/create-campaign-brief/references/zero-shot-iteration-rules.md +66 -0
- package/skills/create-campaign-v2/SKILL.md +1619 -0
- package/skills/create-campaign-v2/core/auto-execute.README.md +219 -0
- package/skills/create-campaign-v2/core/auto-execute.yaml +121 -0
- package/skills/create-campaign-v2/core/flow.v2.json +1643 -0
- package/skills/create-campaign-v2/core/policy.md +82 -0
- package/skills/create-campaign-v2/references/ai-tells.md +253 -0
- package/skills/create-campaign-v2/references/approval-gate-framing.md +346 -0
- package/skills/create-campaign-v2/references/draft-lifecycle.md +110 -0
- package/skills/create-campaign-v2/references/escalation-ladder.md +119 -0
- package/skills/create-campaign-v2/references/filter-leads.md +495 -0
- package/skills/create-campaign-v2/references/final-handoff-contract.md +176 -0
- package/skills/create-campaign-v2/references/gold-standard-message-examples.md +394 -0
- package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +314 -0
- package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +212 -0
- package/skills/create-campaign-v2/references/lead-validation-preview.md +172 -0
- package/skills/create-campaign-v2/references/parallel-critique-protocol.md +368 -0
- package/skills/create-campaign-v2/references/sample-validation-loop.md +289 -0
- package/skills/create-campaign-v2/references/step-13-import-leads.md +151 -0
- package/skills/create-campaign-v2/references/step-15-re-cascade.md +90 -0
- package/skills/create-campaign-v2/references/thomas-revision-filters.md +521 -0
- package/skills/create-campaign-v2/references/thomas-variant-selection.md +202 -0
- package/skills/create-campaign-v2/references/tier-routing-matrix.md +66 -0
- package/skills/create-campaign-v2/references/validation-criteria.md +367 -0
- package/skills/create-campaign-v2/references/watch-link-handoff.md +106 -0
- package/skills/create-campaign-v2-validation/SKILL.md +296 -0
- package/skills/create-post/SKILL.md +1308 -0
- package/skills/create-rubric/SKILL.md +251 -0
- package/skills/engage/SKILL.md +549 -0
- package/skills/engage/core/README.md +23 -0
- package/skills/engage/core/proven-searches.json +11 -0
- package/skills/engage/core/style-guide.template.md +47 -0
- package/skills/engage/core/tracked-people.json +10 -0
- package/skills/enrich-prospects/SKILL.md +97 -0
- package/skills/find-leads/SKILL.md +467 -0
- package/skills/generate-messages/SKILL.md +2361 -0
- package/skills/interview/SKILL.md +132 -0
- package/skills/interview/core/ENGAGE_STYLE_GUIDE.template.md +54 -0
- package/skills/interview/core/ICP.template.md +54 -0
- package/skills/interview/core/VOICE_PROFILE.template.md +101 -0
- package/skills/providers/apollo.md +520 -0
- package/skills/providers/prospeo.md +398 -0
- package/skills/providers/sales-nav.md +372 -0
- package/skills/providers/signal-discovery.md +495 -0
- package/skills/research/SKILL.md +258 -0
- package/skills/research/config.json +9 -0
- package/skills/research/override.md +13 -0
- package/skills/research-prospect/SKILL.md +99 -0
- package/skills/research-sender/SKILL.md +158 -0
- package/skills/workflow-sequences/SKILL.md +85 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
# Thomas Revision Filters
|
|
2
|
+
|
|
3
|
+
Use these filters before Phase 84 message validation is marked `confirmed`.
|
|
4
|
+
|
|
5
|
+
Read "What Good Looks Like" first. These are the positive targets. Use
|
|
6
|
+
"Automatic Revisions" as the rejection backstop, not the primary lens.
|
|
7
|
+
|
|
8
|
+
## What Good Looks Like
|
|
9
|
+
|
|
10
|
+
**Voice and reader experience**
|
|
11
|
+
|
|
12
|
+
- reads like a sharp human operator, not a mail-merge template
|
|
13
|
+
- sentences sound typed, not assembled — varied length, plain words, no
|
|
14
|
+
framework seams
|
|
15
|
+
- a busy buyer could skim it in under ten seconds and get the idea
|
|
16
|
+
- the tone matches the Primary Example's reading level (casual-lowercase if
|
|
17
|
+
Superpower, dense-credentialed if Superposition — don't flatten)
|
|
18
|
+
|
|
19
|
+
**Relevance and grounding**
|
|
20
|
+
|
|
21
|
+
- specific to the validated lead and signal; removing the personalization
|
|
22
|
+
would make the message feel clearly off for this buyer
|
|
23
|
+
- every proof claim traces back to something the brief actually supports
|
|
24
|
+
- every token traces back to a declared source field
|
|
25
|
+
|
|
26
|
+
**Motion alignment**
|
|
27
|
+
|
|
28
|
+
- matches the quality bar of one archived motion, not a blend of two
|
|
29
|
+
- opens with the strongest concrete hook the brief supports (event > signal >
|
|
30
|
+
job > workflow observation)
|
|
31
|
+
- proof sits where the motion expects it (body line for event/signal, stacked
|
|
32
|
+
body for job-post, short `PS` for stack-replacement / proof-led fallback)
|
|
33
|
+
- the CTA is useful and proportional to buyer intent — not a naked meeting
|
|
34
|
+
ask, not a fabricated asset
|
|
35
|
+
|
|
36
|
+
**Craft**
|
|
37
|
+
|
|
38
|
+
- one observation or one pain in the opener, not both stacked
|
|
39
|
+
- 3 short body paragraphs max, **one sentence per line** (literal — two sentences on one line is a revision)
|
|
40
|
+
- sentences at or below ~15 words, or split into shorter lines when longer
|
|
41
|
+
- plain English — a 5th-grade reader should follow the whole message without stopping
|
|
42
|
+
- jargon is limited to brief-native product and tool names (e.g. Shopify, HubSpot, Salesforce, ServiceNow) — not glue language, which is any B2B compound noun the buyer wouldn't say naturally in conversation
|
|
43
|
+
- mechanism said once, directly (product-name-first when the product can carry the sentence)
|
|
44
|
+
- if the mechanism touches three workflows, pick the most painful one or break them into short lines
|
|
45
|
+
- PS reads like one human telling another why the sender gets their pain — at most two proof beats, connected into a sentence or two, first names preferred
|
|
46
|
+
- the sample set reads like siblings from one campaign, not three experiments
|
|
47
|
+
- the Finalizer Pass result is better than any single candidate, or one candidate is named the sweep and the winning axis is declared
|
|
48
|
+
|
|
49
|
+
## Automatic Revisions
|
|
50
|
+
|
|
51
|
+
Revise or reject the sample when any of these happen.
|
|
52
|
+
|
|
53
|
+
**Token and proof safety**
|
|
54
|
+
|
|
55
|
+
- unresolved `{{token}}`
|
|
56
|
+
- unsupported token not documented in the brief
|
|
57
|
+
- invented metric, logo, customer, funding detail, or product claim
|
|
58
|
+
- personalization that cannot be traced to `lead-sample.json`
|
|
59
|
+
- the message has no compelling proof even though the brief supports one
|
|
60
|
+
- stronger safe proof exists in the brief but the draft settles for weaker
|
|
61
|
+
generic credibility
|
|
62
|
+
|
|
63
|
+
**Voice and inbox readability**
|
|
64
|
+
|
|
65
|
+
- generic praise, compliment-sandwich openers, or filler flattery
|
|
66
|
+
- weak observational hooks that could fit almost anyone
|
|
67
|
+
- copy that sounds like a template with the company name swapped in
|
|
68
|
+
- **sentences above ~15 words, or with more than one comma, when they could be split**
|
|
69
|
+
- **two or more sentences on the same line with no blank line between them** — default is one sentence per paragraph, blank line between every sentence in the body
|
|
70
|
+
- **body renders as multi-sentence paragraphs** instead of one-sentence paragraphs separated by blank lines
|
|
71
|
+
- **a single mechanism line that stacks three workflows together** as a comma list (e.g. "order intake, inventory sync, and reorder timing"). Give each workflow its own one-sentence paragraph, or pick the most painful one and drop the others
|
|
72
|
+
- **product clarity failure**: a cold reader cannot state what the product does in one sentence after reading. The mechanism gestures at "that chain", "the stack", or "that work" without a crisp `Product is an X that does Y` anchor sentence and/or without naming specific actions
|
|
73
|
+
- **missing "what the product IS" anchor** — the action breakdown appears without a one-sentence statement of what the product is. The reader needs to know the product category before the actions make sense
|
|
74
|
+
- **actions are implied, not stated** — e.g. "runs that chain as AI agents" when a clearer version would name the specific actions (verb + object, one per line)
|
|
75
|
+
- **category-level opener used when a per-lead signal exists** — if `lead-sample.json` carries any per-lead signal (post, hire, visible tool, topic engagement), the opener must reference it. Category-level openers of shape `"Most [category] teams still do X by hand"` are only acceptable when zero per-lead signal is in the sample. When a category-level opener is used as fallback, Findings must flag it explicitly
|
|
76
|
+
- **mind-reading from engagement signals** — a topic engagement, post, public activity, role, company, or hiring trigger does not prove buyer intent. Reject phrases like `"AI-GTM stack is clearly on your mind"`, `"you're clearly focused on..."`, `"obviously relevant"`, or `"already thinking about..."` unless that exact priority is explicitly present in `lead-sample.json`. Translate to low-certainty buyer context or omit the signal from copy.
|
|
77
|
+
- **source-y signal narration** — reject `"saw you on..."`, `"saw you around..."`, `"saw you engaging with..."`, `"your LinkedIn activity..."`, or any line that makes the recipient feel watched unless the chosen archived motion is intentionally self-aware about the signal. Translate the signal into a natural buyer-context line or omit it.
|
|
78
|
+
- **internal-metric flex** — reject compute time, token/cache details, model names, agent-counts, orchestration internals, or similar process metrics unless the brief proves the buyer cares about that exact detail. `~5 min of compute per message` is not buyer value by itself.
|
|
79
|
+
- **action lines are parallel (same subject, e.g. `It X` / `It Y` / `It Z`) but rendered as one-line paragraphs instead of bullets** — parallel action lines are the bullet case. One-line paragraphs are only for actions that carry a short narrative clause
|
|
80
|
+
- **PS carries a second proof beat that doesn't answer a different objection** — the second beat must open a dimension beat #1 didn't address (e.g. technical reliability when beat #1 was operator empathy; named backing when beat #1 was founder track record). Default PS is ONE beat
|
|
81
|
+
- **subject line uses the same banned glue jargon as the body** — any B2B compound noun the buyer wouldn't say naturally in conversation. Subject follows the same jargon rules as the body
|
|
82
|
+
- **jargon that a 5th-grade reader could not parse** — any B2B compound noun the buyer wouldn't say naturally in conversation. Common examples across motions: "handoff", "rip-and-replace", "pane of glass", "single source of truth", "alert fatigue", "top of funnel", "time to hire". Keep product and tool names that the buyer recognizes; cut the glue language around them
|
|
83
|
+
- em dashes in copy that is otherwise plainspoken
|
|
84
|
+
- repeated metaphor framing makes the sample set feel machine-generated
|
|
85
|
+
- the note reads above a 5th-grade reading level when the motion does not require technical jargon
|
|
86
|
+
|
|
87
|
+
**PS shape and social proof**
|
|
88
|
+
|
|
89
|
+
- **the PS lands as a resume list** (three credential sentences in a row, separated only by periods). Rewrite as a thin narrative of at most two proof beats
|
|
90
|
+
- **proof beats are stacked with no connective tissue** — e.g. "CEO X did A. CTO Y did B. Backer Z." No human writes proof like that in an inbox note
|
|
91
|
+
- **full titles in the PS when the bare role word would read more natural** — "our CEO [did X]" reads more natural than "CEO Alex, 2x founder, [did X]". Drop titles unless the title itself is the proof
|
|
92
|
+
- more than two proof beats in the PS (three or more reads as a resume dump)
|
|
93
|
+
- a proof beat that is not tied to the buyer's situation — proof should explain why this sender gets the buyer's pain, not just list credentials
|
|
94
|
+
|
|
95
|
+
**Motion alignment**
|
|
96
|
+
|
|
97
|
+
- a concrete validated hook exists but the opener falls back to generic pain
|
|
98
|
+
- an abstract noun subject line when a concrete event/signal/asset/offer
|
|
99
|
+
subject was available
|
|
100
|
+
- the draft blends multiple example motions into one overbuilt message
|
|
101
|
+
- a matched archived winner is the same company as the brief, but the draft
|
|
102
|
+
rewrites its casing, spacing, or proof order anyway
|
|
103
|
+
- the three sample messages don't feel like siblings from one campaign
|
|
104
|
+
- a signal-led note had a clean chance to sound like an honest operator but
|
|
105
|
+
got polished into generic sales copy
|
|
106
|
+
|
|
107
|
+
**Fallback (proof-led specialist) drift**
|
|
108
|
+
|
|
109
|
+
- opens with "most teams..." / "scaling X..." without a concrete
|
|
110
|
+
buyer-language workflow anchor
|
|
111
|
+
- opens with synthesized "running X means..." / "being Y means..." framing
|
|
112
|
+
- leans on "at your stage" or "in a setup like yours"
|
|
113
|
+
- mechanism hides behind "we built..." / "we created..." when the product
|
|
114
|
+
name can carry the sentence
|
|
115
|
+
- stack-replacement copy never names the workflow pieces or the breaking
|
|
116
|
+
handoff even though the brief supports them
|
|
117
|
+
- invents a report, brief, teardown, video, or other lead magnet the brief
|
|
118
|
+
never said exists
|
|
119
|
+
- defaults to "can I send it over?" / "send a short overview" when the
|
|
120
|
+
motion is conversational
|
|
121
|
+
|
|
122
|
+
**CTA and structure**
|
|
123
|
+
|
|
124
|
+
- a CTA heavier than the proof and signal support
|
|
125
|
+
- asks for a meeting without offering a useful next step
|
|
126
|
+
- a `PS` appears anywhere other than as the final line
|
|
127
|
+
- a single sample stacks too many ideas (long opener + product explanation +
|
|
128
|
+
proof dump + CTA in one dense block)
|
|
129
|
+
|
|
130
|
+
**Finalizer discipline**
|
|
131
|
+
|
|
132
|
+
- three candidates drafted but no winner declared
|
|
133
|
+
- winner named "hybrid" without naming which candidate each borrowed piece
|
|
134
|
+
came from
|
|
135
|
+
- winner claimed to sweep without declaring the winning axis
|
|
136
|
+
- token fill rules unclear enough that the copy looks guessed
|
|
137
|
+
|
|
138
|
+
## Substance Filters (block the message until fixed)
|
|
139
|
+
|
|
140
|
+
These filters sit ABOVE the "Automatic Revisions" list — they check whether
|
|
141
|
+
the message has any substance at all, not just whether the lint passes.
|
|
142
|
+
A candidate that fails ANY of these five filters is BLOCKED. The finalizer
|
|
143
|
+
pass CANNOT select a blocked candidate. If all 3 candidates fail, route to
|
|
144
|
+
`revise-message` with the failure reasons enumerated per candidate.
|
|
145
|
+
|
|
146
|
+
The "Automatic Revisions" list catches syntax and voice issues. Substance
|
|
147
|
+
Filters catch the polished-looking spam that passes lint but has no reason
|
|
148
|
+
to exist in this specific recipient's inbox.
|
|
149
|
+
|
|
150
|
+
### Filter 1 — Earned-right filter
|
|
151
|
+
|
|
152
|
+
**Rule.** At least ONE line in the body MUST cite something specific to
|
|
153
|
+
the recipient that is verifiable in `lead-sample.json` for THAT row: a
|
|
154
|
+
post excerpt, profile-summary phrase, hiring-trigger, recent-funding
|
|
155
|
+
event, mutual connection, or company-event. If the message contains ZERO
|
|
156
|
+
recipient-specific signals, it has no earned right to the inbox.
|
|
157
|
+
|
|
158
|
+
**Example of a violation** (from the Ambral wrongly-approved winner):
|
|
159
|
+
|
|
160
|
+
> "Your mid-market and SMB book is where NDR hides — not enough AMs to
|
|
161
|
+
> cover it." — this opens with a 3-presumption accusation and cites zero
|
|
162
|
+
> row-specific signal.
|
|
163
|
+
|
|
164
|
+
**Route.** REJECT the candidate. Route to `revise-filter` when the signal
|
|
165
|
+
is missing because the lead source itself is thin (e.g., Sales Nav lane
|
|
166
|
+
with no post data). Route to `revise-message` when the signal IS present
|
|
167
|
+
in `lead-sample.json` but the draft ignored it.
|
|
168
|
+
|
|
169
|
+
### Filter 2 — Presumption filter
|
|
170
|
+
|
|
171
|
+
**Rule.** The opener CANNOT assert facts about the recipient's business
|
|
172
|
+
that are not validated in `lead-sample.json` — book size, NDR location,
|
|
173
|
+
churn rate, staffing level, segment coverage, or any other claim about
|
|
174
|
+
how their team is structured or what their numbers look like. If asserted
|
|
175
|
+
as fact without lead-sample evidence, the message sounds like a cold
|
|
176
|
+
SDR reading from a guess.
|
|
177
|
+
|
|
178
|
+
Signals must also avoid intent certainty. Engagement with a topic proves
|
|
179
|
+
only that the person touched the topic publicly; it does not prove the
|
|
180
|
+
topic is "on their mind," a priority, a budget line, or an active project.
|
|
181
|
+
Use signals as a light reason for sending the note, not as a diagnosis.
|
|
182
|
+
If the natural wording would be `saw you on/around...`, the signal is
|
|
183
|
+
probably better used for targeting than copy.
|
|
184
|
+
|
|
185
|
+
**Example of a violation** (Ambral winner):
|
|
186
|
+
|
|
187
|
+
> "Your mid-market and SMB book is where NDR hides — not enough AMs to
|
|
188
|
+
> cover it." — asserts THREE unvalidated facts (book structure, NDR
|
|
189
|
+
> location, staffing deficit) in one sentence, none traced to the row.
|
|
190
|
+
|
|
191
|
+
**Route.** REJECT. Soften to "Most VPs of CS we talk to see..." pattern
|
|
192
|
+
framing (makes it an industry observation, not an accusation), OR drop
|
|
193
|
+
the assertion entirely and lead with a real signal. Route to
|
|
194
|
+
`revise-message`.
|
|
195
|
+
|
|
196
|
+
### Filter 3 — Vague-proof filter
|
|
197
|
+
|
|
198
|
+
**Rule.** Phrases like "multi-billion-dollar enterprises", "Fortune 500
|
|
199
|
+
companies", "leading SaaS", "top scale-ups", or "major brands" without a
|
|
200
|
+
NAMED example are vapor proof. Cold buyers read these and think "name
|
|
201
|
+
one." Vapor proof is worse than no proof — it signals the sender has
|
|
202
|
+
nothing real to point to. Either strip to mechanism-only, or name a
|
|
203
|
+
specific customer (with permission, from the brief's safe-claims).
|
|
204
|
+
|
|
205
|
+
**Example of a violation** (Ambral winner):
|
|
206
|
+
|
|
207
|
+
> "We're deploying Ambral Cortex — AI Account Managers — inside
|
|
208
|
+
> multi-billion-dollar enterprises to close exactly that gap." — named
|
|
209
|
+
> customer count: zero.
|
|
210
|
+
|
|
211
|
+
**Route.** REJECT. Two acceptable rewrites:
|
|
212
|
+
(a) strip the proof line and keep only the mechanism sentence ("It
|
|
213
|
+
detects revenue signals across CRM + Slack + Gong + ZoomInfo and drafts
|
|
214
|
+
QBR follow-ups");
|
|
215
|
+
(b) name a specific customer from the brief's safe-claims list.
|
|
216
|
+
Route to `revise-message` (mechanism exists) or `revise-brief` (brief's
|
|
217
|
+
safe-claims are empty or too weak to name any customer).
|
|
218
|
+
|
|
219
|
+
### Filter 4 — Read-as-1:1 filter
|
|
220
|
+
|
|
221
|
+
**Rule.** Explicit gate — could this exact message body be sent
|
|
222
|
+
UNCHANGED to 50 OTHER recipients in the sample and read plausibly to
|
|
223
|
+
each? If yes, the message is broadcast spam dressed up as a 1:1 note.
|
|
224
|
+
Force at least one row-specific reference (post quote, profile phrase,
|
|
225
|
+
hire trigger, named company event) that makes the message meaningfully
|
|
226
|
+
different for THIS recipient.
|
|
227
|
+
|
|
228
|
+
**Example of a violation** (Ambral winner):
|
|
229
|
+
|
|
230
|
+
> The entire Ambral Variant A body — opener, mechanism, founder-origin,
|
|
231
|
+
> CTA — could be sent unchanged to every one of the 14 FIT rows and 16
|
|
232
|
+
> non-FIT rows in `lead-sample.json`. Nothing in it points at the
|
|
233
|
+
> specific recipient.
|
|
234
|
+
|
|
235
|
+
**Route.** REJECT. This is the spam check. Route to `revise-message`
|
|
236
|
+
when `lead-sample.json` carries row-specific signal the draft ignored;
|
|
237
|
+
route to `revise-filter` when the sample genuinely has no row-level
|
|
238
|
+
signal to pull from (the real fix is upstream — find-leads should
|
|
239
|
+
surface post data / hire triggers / visible tools before messaging).
|
|
240
|
+
|
|
241
|
+
### Filter 5 — Founder-origin coherence filter
|
|
242
|
+
|
|
243
|
+
**Rule.** If a founder-origin line is included, the IMMEDIATELY-FOLLOWING
|
|
244
|
+
sentence MUST explicitly explain how that experience created the product
|
|
245
|
+
mechanism. The bridge CANNOT be corporate abstraction ("intimacy at
|
|
246
|
+
scale", "operator empathy", "insight at velocity") — it must be a
|
|
247
|
+
CONCRETE mechanism sentence that names an action the product takes or a
|
|
248
|
+
system it connects.
|
|
249
|
+
|
|
250
|
+
**Example of a violation** (Ambral winner):
|
|
251
|
+
|
|
252
|
+
> "I woke up at 4am for a year delivering customer breakfasts at Wonder.
|
|
253
|
+
> The intimacy that was impossible to staff at scale is what Cortex
|
|
254
|
+
> does." — the bridge ("intimacy... is what Cortex does") is corporate
|
|
255
|
+
> abstraction; it does NOT tell the reader what Cortex actually does.
|
|
256
|
+
|
|
257
|
+
**Example that would PASS** (IncidentFox equivalent):
|
|
258
|
+
|
|
259
|
+
> "I spent 2.5 years on-call at Roblox hunting the same chaos. That's
|
|
260
|
+
> why IncidentFox ships a pod that debugs your network in production,
|
|
261
|
+
> not a dashboard." — the bridge names a concrete mechanism
|
|
262
|
+
> (ships-a-pod, debugs-network-in-pod), tied directly to the prior-role
|
|
263
|
+
> pain.
|
|
264
|
+
|
|
265
|
+
**Route.** REJECT. Two acceptable rewrites:
|
|
266
|
+
(a) drop the founder-origin line entirely and lead with the mechanism;
|
|
267
|
+
(b) rewrite the bridge to name a concrete action the product takes,
|
|
268
|
+
tied causally to the origin experience.
|
|
269
|
+
Route to `revise-message`.
|
|
270
|
+
|
|
271
|
+
### Filter 6 — Anti-AI-tell filter
|
|
272
|
+
|
|
273
|
+
**Rule.** Reject the candidate if the body contains ANY of the
|
|
274
|
+
following AI-tell patterns. These are the signals that make a cold
|
|
275
|
+
message read as "AI-generated from a scrape" instead of "a founder
|
|
276
|
+
typed this about something they're working on."
|
|
277
|
+
|
|
278
|
+
1. **Date or duration references about the recipient.** Phrases that
|
|
279
|
+
name a specific date, month, or tenure length on the recipient's
|
|
280
|
+
timeline — "last month", "yesterday", "six months ago", "six months
|
|
281
|
+
into your CTO seat", "since 2023", verbatim post dates
|
|
282
|
+
("2026-03-16"). Cold operators don't say this. Drop the date or
|
|
283
|
+
re-cast as a natural callback ("saw your recent post about..." →
|
|
284
|
+
not "on March 16 you posted...").
|
|
285
|
+
2. **Block-quoted verbatim recipient phrases longer than 4 words
|
|
286
|
+
inside quotation marks.** Long quote-backs announce that the sender
|
|
287
|
+
scraped the recipient. Compress to 2-4 words OR paraphrase into
|
|
288
|
+
natural language ("you wrote about runbook troubleshooters" beats
|
|
289
|
+
`"deployment fixer and troubleshooter ... runbook troubleshooter"`
|
|
290
|
+
with the block-quote punctuation).
|
|
291
|
+
3. **Explicit-source-citation phrases.** `"Your bio says"`, `"your
|
|
292
|
+
profile shows"`, `"the post you wrote"`, `"the req you posted"`,
|
|
293
|
+
`"saw on your LinkedIn"`, `"your X-page mentions"`. These
|
|
294
|
+
phrases are the prose equivalent of showing your work — humans
|
|
295
|
+
don't narrate the source of their knowledge when DMing a peer.
|
|
296
|
+
Drop the source-narration frame; reference the signal as if it
|
|
297
|
+
were obvious background.
|
|
298
|
+
4. **Stack/feature lists in parentheses.** `"(Datadog / PagerDuty /
|
|
299
|
+
GitHub / AWS)"`, `"(Slack + Linear + GitHub)"`, `"(Stripe,
|
|
300
|
+
HubSpot, Zendesk)"`. Parenthetical tool dumps read as a
|
|
301
|
+
machine-assembled integration list. Either name ONE relevant tool
|
|
302
|
+
inline or drop the parenthetical entirely.
|
|
303
|
+
5. **Over-precise numerics that a human wouldn't type.** `"2 Q1 2026
|
|
304
|
+
pilot partners"`, `"spent the last eight years"`, `"three failure
|
|
305
|
+
modes"`, `"27% of our sample"`. Founders write casually: "a couple
|
|
306
|
+
pilots this quarter", "you've been at this a while", "the same
|
|
307
|
+
kinds of failures", "about a quarter". Round, hedge, or drop.
|
|
308
|
+
|
|
309
|
+
**Example of a violation** (IncidentFox rerun-4 winner):
|
|
310
|
+
|
|
311
|
+
> "Nedko — your BioRender post last month on the internal governance
|
|
312
|
+
> dashboard called out "deployment fixer and troubleshooter" and
|
|
313
|
+
> "runbook troubleshooter" as high-value use cases."
|
|
314
|
+
|
|
315
|
+
Three tells stacked in one sentence: date reference ("last month"),
|
|
316
|
+
two block-quoted phrases >4 words, and implicit source-citation
|
|
317
|
+
frame ("your BioRender post").
|
|
318
|
+
|
|
319
|
+
**Natural alternative** (same signal, no tells):
|
|
320
|
+
|
|
321
|
+
> "Saw you've been writing about runbook troubleshooters and
|
|
322
|
+
> deployment fixers — that's almost exactly the class of work we
|
|
323
|
+
> built the product around."
|
|
324
|
+
|
|
325
|
+
**Route.** REJECT. Route to `revise-message`.
|
|
326
|
+
|
|
327
|
+
### Filter 7 — Anti-talk-at filter
|
|
328
|
+
|
|
329
|
+
**Rule.** The OPENING SENTENCE must not lead with a
|
|
330
|
+
recipient-specific reference. The opener must establish sender
|
|
331
|
+
reality FIRST — what we're building, who we are, why we're reaching
|
|
332
|
+
out — before any callback to the recipient. A "talk-at" opener reads
|
|
333
|
+
like a cold-scraper addressing a target; a "sender-first" opener
|
|
334
|
+
reads like a founder introducing themselves.
|
|
335
|
+
|
|
336
|
+
**Detection patterns to REJECT as the opener (non-exhaustive):**
|
|
337
|
+
|
|
338
|
+
- `{{first_name}} — saw you...`
|
|
339
|
+
- `{{first_name}} — your [X]...`
|
|
340
|
+
- `Your [X] is...`
|
|
341
|
+
- `Saw the [X] you posted...`
|
|
342
|
+
- `I noticed your...`
|
|
343
|
+
- `Six months into your...`
|
|
344
|
+
- `Your [company] post last month...`
|
|
345
|
+
- `Just read your [X]...`
|
|
346
|
+
|
|
347
|
+
Recipient-specific gravity MAY appear in body sentences 2-4 as a
|
|
348
|
+
LIGHT callback (one casual sentence, no verbatim quote, no date
|
|
349
|
+
reference), but never as the lede. The first impression must read
|
|
350
|
+
as "a founder reaching out about something they built" — not
|
|
351
|
+
"someone who scraped me."
|
|
352
|
+
|
|
353
|
+
**Acceptable opener shapes (sender-first):**
|
|
354
|
+
|
|
355
|
+
- `Hey {{first_name}}, I'm building [X] — [what it does in one plain
|
|
356
|
+
sentence].`
|
|
357
|
+
- `Hey {{first_name}}, quick one. My co-founder and I left [prior
|
|
358
|
+
role] to build [X].`
|
|
359
|
+
- `Hey {{first_name}}, reaching out because [one-line sender
|
|
360
|
+
context] and [one-line what we're building].`
|
|
361
|
+
- `Hey {{first_name}}, [product] — [one-sentence mechanism].`
|
|
362
|
+
|
|
363
|
+
Then, sentences 2-4 may include a LIGHT callback to the recipient:
|
|
364
|
+
`"Thought of [company] because..."`, `"Feels relevant to the
|
|
365
|
+
[recipient's area] work you've been doing."`, `"Saw you're working on
|
|
366
|
+
[area]."` (NOT `"saw the [X] you posted on [date]"`.)
|
|
367
|
+
|
|
368
|
+
**Example of a violation** (IncidentFox rerun-4 winner opener):
|
|
369
|
+
|
|
370
|
+
> "Nedko — your BioRender post last month on the internal governance
|
|
371
|
+
> dashboard called out [...]"
|
|
372
|
+
|
|
373
|
+
Opens with recipient reference + date + source citation. Reads as
|
|
374
|
+
"I scraped you." Zero sender context before the first sentence
|
|
375
|
+
ends.
|
|
376
|
+
|
|
377
|
+
**Natural alternative** (sender-first, light callback in sentence 3):
|
|
378
|
+
|
|
379
|
+
> "Hey Nedko, my co-founder and I left Roblox to build IncidentFox —
|
|
380
|
+
> an AI SRE that lives in Slack and posts a root-cause hypothesis
|
|
381
|
+
> before a human wakes up.
|
|
382
|
+
>
|
|
383
|
+
> It auto-builds its integrations from your codebase, so deployment
|
|
384
|
+
> goes from "paste the API keys" to "it's already reading your repo."
|
|
385
|
+
>
|
|
386
|
+
> Thought of BioRender because you've been writing publicly about
|
|
387
|
+
> runbook troubleshooters, which is almost exactly the class of
|
|
388
|
+
> work we built around."
|
|
389
|
+
|
|
390
|
+
Opener establishes who's sending and what they built. The
|
|
391
|
+
recipient callback arrives in sentence 3, paraphrased, no date, no
|
|
392
|
+
block quote.
|
|
393
|
+
|
|
394
|
+
**Route.** REJECT. Route to `revise-message`.
|
|
395
|
+
|
|
396
|
+
### Filter 8 — AI-tells filter (catalog-backed)
|
|
397
|
+
|
|
398
|
+
**Rule.** Reject if the candidate contains any pattern marked
|
|
399
|
+
`REJECT` in the canonical catalog at
|
|
400
|
+
`references/ai-tells.md`. Surface as a warning (do not auto-block)
|
|
401
|
+
if the candidate contains any pattern marked `WARN`.
|
|
402
|
+
|
|
403
|
+
The canonical catalog lives at
|
|
404
|
+
`mcp/sellable/skills/create-campaign-v2/references/ai-tells.md`. It
|
|
405
|
+
is the single source of truth for all AI-tell patterns. Add new
|
|
406
|
+
tells to that file directly — do NOT bloat this filter spec.
|
|
407
|
+
|
|
408
|
+
**Mandatory check.** For each candidate in the sample:
|
|
409
|
+
|
|
410
|
+
1. Read `references/ai-tells.md`.
|
|
411
|
+
2. For each `Tell #N` entry, run the pattern against the candidate
|
|
412
|
+
body.
|
|
413
|
+
3. If any `REJECT`-severity tell matches, mark the candidate BLOCKED
|
|
414
|
+
with `Filter 8 — AI-tells (Tell #N: [title])` and move on.
|
|
415
|
+
4. If any `WARN`-severity tell matches, surface in the candidate's
|
|
416
|
+
Substance Filter gate table but do NOT auto-block.
|
|
417
|
+
5. A candidate blocked by Filter 8 cannot be selected as the winner.
|
|
418
|
+
|
|
419
|
+
**Note on Filter 3 and Filter 6 overlap.** Several tells in the
|
|
420
|
+
catalog (Tell #3 date refs, Tell #4 block-quotes, Tell #5 source-
|
|
421
|
+
citation, Tell #6 parenthetical stack, Tell #7 over-precise numerics,
|
|
422
|
+
Tell #8 hardcoded signoff, Tell #10 vague-proof) overlap with
|
|
423
|
+
Filters 3 and 6. This is intentional — the catalog is the canonical
|
|
424
|
+
enumeration; Filter 8 is the catalog-driven check. Filters 3 and 6
|
|
425
|
+
remain as human-readable explanations of specific high-priority
|
|
426
|
+
tell classes, but the actual detection logic in Phase-84 reads from
|
|
427
|
+
`ai-tells.md`.
|
|
428
|
+
|
|
429
|
+
**Adding new tells.** When UAT surfaces a new AI-tell pattern, add
|
|
430
|
+
it as `Tell #N` in `ai-tells.md` with Pattern / Why / Allowed
|
|
431
|
+
alternative / Severity. The next Phase-84 run picks it up
|
|
432
|
+
automatically. Update
|
|
433
|
+
`tests/scripts/skill-references-substance-filters.test.ts` if the
|
|
434
|
+
new tell needs regression coverage.
|
|
435
|
+
|
|
436
|
+
**Example of a violation** (Plan 05 Patientdesk winner, pre-catalog —
|
|
437
|
+
Tell #1 body-level self-introduction):
|
|
438
|
+
|
|
439
|
+
> "Hey Bonnie — Oncel here. My co-founders and I ran our own dental
|
|
440
|
+
> call center for two years before building Patientdesk..."
|
|
441
|
+
|
|
442
|
+
The `"Oncel here."` clause is the Tell #1 pattern. The recipient
|
|
443
|
+
already sees "Oncel Ozgul / Co-founder & CEO @ Patientdesk.ai" from
|
|
444
|
+
the LinkedIn sender strip. Repeating the name in the body adds
|
|
445
|
+
nothing except a template-aroma.
|
|
446
|
+
|
|
447
|
+
**Acceptable rewrites** (same substance, no Tell #1):
|
|
448
|
+
|
|
449
|
+
> "Hey Bonnie — pre-Patientdesk, my co-founders and I ran our own
|
|
450
|
+
> dental call center for two years; every missed call was a real
|
|
451
|
+
> number on our P&L."
|
|
452
|
+
|
|
453
|
+
> "Hey Bonnie — quick one. We built Patientdesk out of running our
|
|
454
|
+
> own dental call center for two years, where every missed call hit
|
|
455
|
+
> the P&L directly."
|
|
456
|
+
|
|
457
|
+
> "Hey Bonnie — building a thing for group dentistry I think you'd
|
|
458
|
+
> have an opinion on. My co-founders and I ran our own dental call
|
|
459
|
+
> center for two years before this..."
|
|
460
|
+
|
|
461
|
+
All three open with substance (what we built / the reality that led
|
|
462
|
+
to it) and trust the LinkedIn UI to handle sender identity.
|
|
463
|
+
|
|
464
|
+
**Route.** REJECT. Route to `revise-message`.
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
Note: filters 1-4 are evaluated PER CANDIDATE. Filter 5 only applies
|
|
469
|
+
when a founder-origin line is present in the candidate. Filters 6, 7,
|
|
470
|
+
and 8 are evaluated PER CANDIDATE and check for AI-tells, talk-at
|
|
471
|
+
openers, and self-introduction tells respectively. A candidate that
|
|
472
|
+
passes all 8 filters plus the Automatic Revisions list may proceed to
|
|
473
|
+
the Finalizer Pass. A candidate that fails any of the 8 is marked
|
|
474
|
+
BLOCKED in the Candidate Messages section (with the filter name
|
|
475
|
+
cited) and cannot be selected as the winner.
|
|
476
|
+
|
|
477
|
+
## Revision Direction
|
|
478
|
+
|
|
479
|
+
When the message is weak, decide which layer is actually wrong:
|
|
480
|
+
|
|
481
|
+
- revise-message
|
|
482
|
+
- the structure, wording, or CTA is off
|
|
483
|
+
- revise-filter
|
|
484
|
+
- the signal is too noisy or the sample lead is not a clean buyer
|
|
485
|
+
- revise-brief
|
|
486
|
+
- the proof boundary or message thesis in `brief.md` is the real problem
|
|
487
|
+
|
|
488
|
+
Do not patch a weak message by inventing stronger personalization.
|
|
489
|
+
|
|
490
|
+
## Dry-Mode Discipline
|
|
491
|
+
|
|
492
|
+
Phase 84 dry mode is validation, not production drafting.
|
|
493
|
+
|
|
494
|
+
- use only `brief.md`, `lead-filter.md`, and `lead-sample.json`
|
|
495
|
+
- do not fetch new research
|
|
496
|
+
- do not mutate campaign state
|
|
497
|
+
- if the personalization source is missing, remove the token or route back for revision
|
|
498
|
+
- synthesize the structure from the closest archived gold-standard winner
|
|
499
|
+
before reaching for a generic framework
|
|
500
|
+
- retrieve broadly, but preserve one primary example and borrow from at most one
|
|
501
|
+
narrow secondary influence
|
|
502
|
+
|
|
503
|
+
## Plan 85-03 Critique Addendum
|
|
504
|
+
|
|
505
|
+
These filters are also the gate on any critique rewrite shipped by the
|
|
506
|
+
Plan 85-03 parallel critique protocol (see
|
|
507
|
+
`references/parallel-critique-protocol.md`). When the critique flag is
|
|
508
|
+
on, a rewritten message must still clear:
|
|
509
|
+
|
|
510
|
+
- every "Automatic Revisions" check above (jargon, resume-list PS, stacked
|
|
511
|
+
sentences, weak hooks, etc.)
|
|
512
|
+
- the Phase 84 token contract: only supported tokens from the brief, no
|
|
513
|
+
unresolved `{{token}}`, no invented proof, no personalization that can't
|
|
514
|
+
be traced to `lead-sample.json`
|
|
515
|
+
- the Phase 84 finalizer pass when `synthesis.enforceFinalizerPass` is
|
|
516
|
+
`true` (default)
|
|
517
|
+
|
|
518
|
+
If a rewrite fails any of these, the critique pass falls back to the
|
|
519
|
+
plain generated message for that row. Nothing about these filters
|
|
520
|
+
changes because critique is running; they remain the bar the copy
|
|
521
|
+
must clear before persistence.
|