@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.
Files changed (200) hide show
  1. package/.claude-plugin/plugin.json +12 -0
  2. package/.mcp.json +9 -0
  3. package/README.md +355 -0
  4. package/dist/api.d.ts +21 -0
  5. package/dist/api.js +73 -0
  6. package/dist/auth.d.ts +60 -0
  7. package/dist/auth.js +246 -0
  8. package/dist/engage-memory.d.ts +63 -0
  9. package/dist/engage-memory.js +354 -0
  10. package/dist/index-dev.d.ts +2 -0
  11. package/dist/index-dev.js +17 -0
  12. package/dist/index.d.ts +7 -0
  13. package/dist/index.js +8 -0
  14. package/dist/server.d.ts +1 -0
  15. package/dist/server.js +499 -0
  16. package/dist/skills.d.ts +11 -0
  17. package/dist/skills.js +97 -0
  18. package/dist/tools/auth.d.ts +30 -0
  19. package/dist/tools/auth.js +124 -0
  20. package/dist/tools/blueprint-commit.d.ts +174 -0
  21. package/dist/tools/blueprint-commit.js +286 -0
  22. package/dist/tools/bootstrap.d.ts +64 -0
  23. package/dist/tools/bootstrap.js +246 -0
  24. package/dist/tools/campaigns.d.ts +589 -0
  25. package/dist/tools/campaigns.js +892 -0
  26. package/dist/tools/cells.d.ts +58 -0
  27. package/dist/tools/cells.js +48 -0
  28. package/dist/tools/context.d.ts +88 -0
  29. package/dist/tools/context.js +271 -0
  30. package/dist/tools/csv-domains.d.ts +73 -0
  31. package/dist/tools/csv-domains.js +464 -0
  32. package/dist/tools/csv-linkedin.d.ts +102 -0
  33. package/dist/tools/csv-linkedin.js +712 -0
  34. package/dist/tools/direct-campaigns.d.ts +240 -0
  35. package/dist/tools/direct-campaigns.js +250 -0
  36. package/dist/tools/engage-bootstrap.d.ts +94 -0
  37. package/dist/tools/engage-bootstrap.js +205 -0
  38. package/dist/tools/engage-discovery.d.ts +78 -0
  39. package/dist/tools/engage-discovery.js +150 -0
  40. package/dist/tools/engage-memory.d.ts +181 -0
  41. package/dist/tools/engage-memory.js +143 -0
  42. package/dist/tools/engage-state.d.ts +72 -0
  43. package/dist/tools/engage-state.js +62 -0
  44. package/dist/tools/enrichment.d.ts +167 -0
  45. package/dist/tools/enrichment.js +174 -0
  46. package/dist/tools/flow-preflight.d.ts +68 -0
  47. package/dist/tools/flow-preflight.js +138 -0
  48. package/dist/tools/framework.d.ts +44 -0
  49. package/dist/tools/framework.js +153 -0
  50. package/dist/tools/interaction-mode.d.ts +27 -0
  51. package/dist/tools/interaction-mode.js +102 -0
  52. package/dist/tools/leads.d.ts +2417 -0
  53. package/dist/tools/leads.js +2307 -0
  54. package/dist/tools/linkedin.d.ts +210 -0
  55. package/dist/tools/linkedin.js +229 -0
  56. package/dist/tools/navigation.d.ts +91 -0
  57. package/dist/tools/navigation.js +381 -0
  58. package/dist/tools/one-off.d.ts +229 -0
  59. package/dist/tools/one-off.js +273 -0
  60. package/dist/tools/processing.d.ts +70 -0
  61. package/dist/tools/processing.js +56 -0
  62. package/dist/tools/prompts.d.ts +211 -0
  63. package/dist/tools/prompts.js +210 -0
  64. package/dist/tools/provider-preflight.d.ts +21 -0
  65. package/dist/tools/provider-preflight.js +59 -0
  66. package/dist/tools/readiness.d.ts +261 -0
  67. package/dist/tools/readiness.js +510 -0
  68. package/dist/tools/rows.d.ts +126 -0
  69. package/dist/tools/rows.js +105 -0
  70. package/dist/tools/rubrics.d.ts +497 -0
  71. package/dist/tools/rubrics.js +681 -0
  72. package/dist/tools/senders.d.ts +44 -0
  73. package/dist/tools/senders.js +69 -0
  74. package/dist/tools/sequencer.d.ts +127 -0
  75. package/dist/tools/sequencer.js +194 -0
  76. package/dist/tools/tables.d.ts +35 -0
  77. package/dist/tools/tables.js +36 -0
  78. package/dist/tools/verify-row.d.ts +36 -0
  79. package/dist/tools/verify-row.js +38 -0
  80. package/dist/tools/workspaces.d.ts +140 -0
  81. package/dist/tools/workspaces.js +139 -0
  82. package/dist/utils/workspace-root.d.ts +1 -0
  83. package/dist/utils/workspace-root.js +39 -0
  84. package/package.json +46 -0
  85. package/skills/building-gtm-tables/SKILL.md +216 -0
  86. package/skills/building-gtm-tables/core/auto-execute.yaml +19 -0
  87. package/skills/building-gtm-tables/core/blueprint-schema.json +72 -0
  88. package/skills/building-gtm-tables/references/brief-to-blueprint.md +334 -0
  89. package/skills/building-gtm-tables/references/column-type-catalog.md +318 -0
  90. package/skills/building-gtm-tables/references/common-blueprints.fixtures.ts +199 -0
  91. package/skills/building-gtm-tables/references/common-blueprints.md +44 -0
  92. package/skills/building-gtm-tables/references/failure-taxonomy.md +197 -0
  93. package/skills/building-gtm-tables/references/uat-seed-prompts.md +37 -0
  94. package/skills/building-gtm-tables/references/verify-loop.md +74 -0
  95. package/skills/campaign-messages/SKILL.md +173 -0
  96. package/skills/campaign-messages/flow.v1.json +75 -0
  97. package/skills/craft-message/SKILL.md +401 -0
  98. package/skills/create-campaign/ARCHITECTURE.md +232 -0
  99. package/skills/create-campaign/DISCUSS.md +296 -0
  100. package/skills/create-campaign/FLOW_ASCII.md +240 -0
  101. package/skills/create-campaign/HOST-PARITY-CHECKLIST.md +49 -0
  102. package/skills/create-campaign/README.md +142 -0
  103. package/skills/create-campaign/SKILL.md +286 -0
  104. package/skills/create-campaign/context/README.md +67 -0
  105. package/skills/create-campaign/context/_TEMPLATE.md +12 -0
  106. package/skills/create-campaign/context/context.md +35 -0
  107. package/skills/create-campaign/context/learnings.md +16 -0
  108. package/skills/create-campaign/context/registry.json +19 -0
  109. package/skills/create-campaign/core/flow.v1.json +217 -0
  110. package/skills/create-campaign/core/policy.md +191 -0
  111. package/skills/create-campaign/core/providers/apollo.json +35 -0
  112. package/skills/create-campaign/core/providers/prospeo.json +34 -0
  113. package/skills/create-campaign/core/providers/registry.json +31 -0
  114. package/skills/create-campaign/core/providers/sales-nav.json +37 -0
  115. package/skills/create-campaign/core/providers/signal-discovery.json +42 -0
  116. package/skills/create-campaign/references/brief-template.md +64 -0
  117. package/skills/create-campaign/references/campaign-quality.md +84 -0
  118. package/skills/create-campaign/references/copy-calibration-examples.md +120 -0
  119. package/skills/create-campaign/references/offer-patterns.md +108 -0
  120. package/skills/create-campaign/references/provider-selection-strategy.md +212 -0
  121. package/skills/create-campaign/references/question-examples.md +167 -0
  122. package/skills/create-campaign/references/token-fill-examples.md +81 -0
  123. package/skills/create-campaign-brief/ARCHITECTURE.md +72 -0
  124. package/skills/create-campaign-brief/DISCUSS.md +64 -0
  125. package/skills/create-campaign-brief/README.md +176 -0
  126. package/skills/create-campaign-brief/SKILL.md +537 -0
  127. package/skills/create-campaign-brief/references/brief-synthesis-rules.md +100 -0
  128. package/skills/create-campaign-brief/references/brief-template.md +220 -0
  129. package/skills/create-campaign-brief/references/campaign-idea-options.md +30 -0
  130. package/skills/create-campaign-brief/references/copy-appendix-template.md +62 -0
  131. package/skills/create-campaign-brief/references/draft-lifecycle.md +23 -0
  132. package/skills/create-campaign-brief/references/examples/MANIFEST.json +89 -0
  133. package/skills/create-campaign-brief/references/examples/briefs/clover.md +223 -0
  134. package/skills/create-campaign-brief/references/examples/briefs/galley.md +222 -0
  135. package/skills/create-campaign-brief/references/examples/briefs/gelee.md +220 -0
  136. package/skills/create-campaign-brief/references/examples/briefs/hey-digital.md +234 -0
  137. package/skills/create-campaign-brief/references/examples/briefs/persona.md +231 -0
  138. package/skills/create-campaign-brief/references/examples/briefs/revvix.md +220 -0
  139. package/skills/create-campaign-brief/references/examples/briefs/sellable-dev.md +220 -0
  140. package/skills/create-campaign-brief/references/examples/briefs/superposition.md +233 -0
  141. package/skills/create-campaign-brief/references/examples/briefs/superpower.md +219 -0
  142. package/skills/create-campaign-brief/references/examples/briefs/westpark-villas.md +220 -0
  143. package/skills/create-campaign-brief/references/icp-lock-question-bank.md +43 -0
  144. package/skills/create-campaign-brief/references/messaging-inputs.md +58 -0
  145. package/skills/create-campaign-brief/references/output-acceptance-rubric.md +62 -0
  146. package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +248 -0
  147. package/skills/create-campaign-brief/references/phase75-canonical-brief-template.md +319 -0
  148. package/skills/create-campaign-brief/references/phase75-good-brief-and-messaging-examples.md +445 -0
  149. package/skills/create-campaign-brief/references/quick-research-protocol.md +39 -0
  150. package/skills/create-campaign-brief/references/reference-sheet-protocol.md +60 -0
  151. package/skills/create-campaign-brief/references/zero-shot-iteration-rules.md +66 -0
  152. package/skills/create-campaign-v2/SKILL.md +1619 -0
  153. package/skills/create-campaign-v2/core/auto-execute.README.md +219 -0
  154. package/skills/create-campaign-v2/core/auto-execute.yaml +121 -0
  155. package/skills/create-campaign-v2/core/flow.v2.json +1643 -0
  156. package/skills/create-campaign-v2/core/policy.md +82 -0
  157. package/skills/create-campaign-v2/references/ai-tells.md +253 -0
  158. package/skills/create-campaign-v2/references/approval-gate-framing.md +346 -0
  159. package/skills/create-campaign-v2/references/draft-lifecycle.md +110 -0
  160. package/skills/create-campaign-v2/references/escalation-ladder.md +119 -0
  161. package/skills/create-campaign-v2/references/filter-leads.md +495 -0
  162. package/skills/create-campaign-v2/references/final-handoff-contract.md +176 -0
  163. package/skills/create-campaign-v2/references/gold-standard-message-examples.md +394 -0
  164. package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +314 -0
  165. package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +212 -0
  166. package/skills/create-campaign-v2/references/lead-validation-preview.md +172 -0
  167. package/skills/create-campaign-v2/references/parallel-critique-protocol.md +368 -0
  168. package/skills/create-campaign-v2/references/sample-validation-loop.md +289 -0
  169. package/skills/create-campaign-v2/references/step-13-import-leads.md +151 -0
  170. package/skills/create-campaign-v2/references/step-15-re-cascade.md +90 -0
  171. package/skills/create-campaign-v2/references/thomas-revision-filters.md +521 -0
  172. package/skills/create-campaign-v2/references/thomas-variant-selection.md +202 -0
  173. package/skills/create-campaign-v2/references/tier-routing-matrix.md +66 -0
  174. package/skills/create-campaign-v2/references/validation-criteria.md +367 -0
  175. package/skills/create-campaign-v2/references/watch-link-handoff.md +106 -0
  176. package/skills/create-campaign-v2-validation/SKILL.md +296 -0
  177. package/skills/create-post/SKILL.md +1308 -0
  178. package/skills/create-rubric/SKILL.md +251 -0
  179. package/skills/engage/SKILL.md +549 -0
  180. package/skills/engage/core/README.md +23 -0
  181. package/skills/engage/core/proven-searches.json +11 -0
  182. package/skills/engage/core/style-guide.template.md +47 -0
  183. package/skills/engage/core/tracked-people.json +10 -0
  184. package/skills/enrich-prospects/SKILL.md +97 -0
  185. package/skills/find-leads/SKILL.md +467 -0
  186. package/skills/generate-messages/SKILL.md +2361 -0
  187. package/skills/interview/SKILL.md +132 -0
  188. package/skills/interview/core/ENGAGE_STYLE_GUIDE.template.md +54 -0
  189. package/skills/interview/core/ICP.template.md +54 -0
  190. package/skills/interview/core/VOICE_PROFILE.template.md +101 -0
  191. package/skills/providers/apollo.md +520 -0
  192. package/skills/providers/prospeo.md +398 -0
  193. package/skills/providers/sales-nav.md +372 -0
  194. package/skills/providers/signal-discovery.md +495 -0
  195. package/skills/research/SKILL.md +258 -0
  196. package/skills/research/config.json +9 -0
  197. package/skills/research/override.md +13 -0
  198. package/skills/research-prospect/SKILL.md +99 -0
  199. package/skills/research-sender/SKILL.md +158 -0
  200. package/skills/workflow-sequences/SKILL.md +85 -0
@@ -0,0 +1,106 @@
1
+ # Watch Link Handoff
2
+
3
+ This reference governs how create-campaign-v2 surfaces the watch link after
4
+ the commit gate passes and the atomic mint succeeds. Load this file before
5
+ showing the watch link, and on every resume where the link needs to be
6
+ re-surfaced.
7
+
8
+ ## Plumbing Reuse
9
+
10
+ `create_campaign` already returns a signed `watchUrl` on the response
11
+ (`CampaignDetail.watchUrl` in `mcp/sellable/src/tools/campaigns.ts`). V2 does
12
+ NOT mint a new token, does NOT call a different route, and does NOT construct
13
+ the URL locally. The skill captures whatever `watchUrl` the existing tool
14
+ returns and surfaces it verbatim.
15
+
16
+ The v1 `create-campaign` SKILL uses the same "watch mode" pattern: after a
17
+ step change, the skill names what changed and orients the user to what the
18
+ watch link will show next. V2 adopts that pattern verbatim — the only
19
+ difference is V2 surfaces the link once, at the atomic mint boundary, and
20
+ then re-surfaces it on resume.
21
+
22
+ ## Atomic Mint Sequence
23
+
24
+ The watch link is only surfaced after **both** of these tool calls succeed in
25
+ this order:
26
+
27
+ 1. `create_campaign({ campaignBrief, currentStep: "auto-execute-leads" })`
28
+ → response MUST include `{ campaignId, watchUrl }`
29
+ 2. `save_rubrics({ campaignOfferId, rubric })`
30
+ → must return success
31
+
32
+ Both calls must succeed before the link is printed. Never print the link
33
+ between the two calls. Never print the link if either call fails.
34
+
35
+ ## Required Output Block
36
+
37
+ After both tool calls succeed, print exactly one user-facing block. The block
38
+ must contain:
39
+
40
+ - a one-line orientation sentence: `Open this to watch lead sourcing, rubric
41
+ scoring, and messaging populate live.`
42
+ - the `watchUrl` captured from the `create_campaign` response
43
+
44
+ Example skeleton:
45
+
46
+ ```text
47
+ Campaign minted. Open this to watch lead sourcing, rubric scoring, and messaging populate live.
48
+
49
+ Watch link: {watchUrl}
50
+ ```
51
+
52
+ The exact wording may be adapted for tone, but the one-line orientation and
53
+ the `watchUrl` are both required. Do not collapse the block into a single
54
+ line with the link inline — the user needs to see the orientation clearly
55
+ before they click.
56
+
57
+ ## Partial-Mint Recovery
58
+
59
+ The following failure modes must NOT print the watch link:
60
+
61
+ - `create_campaign` errors (no campaign exists, no watchUrl was returned) →
62
+ surface the underlying error, do not proceed to `save_rubrics`. No
63
+ rollback needed.
64
+ - `create_campaign` succeeds but the response is missing `watchUrl` → treat
65
+ as a recoverable failure. Stop before `save_rubrics`. Do not print a link.
66
+ Surface an explicit error that names the contract violation (the backend
67
+ tool should always return `watchUrl`; a missing value is a plumbing bug,
68
+ not a silent skip).
69
+ - `save_rubrics` fails after `create_campaign` succeeds → either rollback the
70
+ `CampaignOffer` row, or mark an explicit recoverable failure state so the
71
+ user can retry rubric save. Never leave a silent partial campaign with no
72
+ rubrics. Do NOT print the watch link during this recovery window.
73
+
74
+ The guiding rule: a watch link points at a live, fully-minted campaign. If
75
+ the campaign is half-minted, the link is misleading and must not be shown.
76
+
77
+ ## Resume Re-Surface
78
+
79
+ Users can quit the session after `approve` and reopen later. Plan 85-02
80
+ handles autonomous tail resume via `CampaignOffer.currentStep`. Part of the
81
+ resume contract is re-surfacing the same watch link so the user reorients
82
+ without digging through prior transcript.
83
+
84
+ On resume:
85
+
86
+ 1. Load the `CampaignOffer` for the campaign being resumed.
87
+ 2. Call the same tool that yielded the link on mint (e.g.
88
+ `create_campaign({ campaignId })`, which is idempotent and returns the
89
+ existing campaign's `watchUrl` + state — see the v1 pattern in
90
+ `mcp/sellable/skills/create-campaign/SKILL.md`).
91
+ 3. Print the same block again with the one-line orientation plus `watchUrl`.
92
+
93
+ The re-surface must use the signed `watchUrl` from the tool response, not a
94
+ cached or reconstructed URL.
95
+
96
+ ## Hard Rules
97
+
98
+ - Surface the link **once** on successful atomic mint, and re-surface on
99
+ resume. Do not spam the link between intermediate autonomous-tail steps.
100
+ - Never print the link while the mint is mid-flight. Both
101
+ `create_campaign` and `save_rubrics` must have succeeded first.
102
+ - Never fabricate or reconstruct the URL locally. Capture it from the
103
+ `create_campaign` response.
104
+ - Missing `watchUrl` in the response is an error, not a silent skip.
105
+ - Partial-mint states (campaign row created but rubrics not saved) must
106
+ block link surfacing and surface the recovery path instead.
@@ -0,0 +1,296 @@
1
+ ---
2
+ name: create-campaign-v2-validation
3
+ description: Validate a Phase 83 `brief.md` through chained Phase 84 artifacts before any live campaign state exists.
4
+ visibility: internal
5
+ ---
6
+
7
+ # Create Campaign v2 Validation
8
+
9
+ <role>
10
+ You are the Phase 84 validation orchestrator for create-campaign-v2. Your job
11
+ is to validate a Phase 83 `brief.md` through chained draft artifacts without
12
+ creating live campaign state.
13
+ </role>
14
+
15
+ <objective>
16
+ Run validation in three serial steps:
17
+
18
+ 1. find leads
19
+ 2. filter leads
20
+ 3. generate message
21
+
22
+ Each step writes its own artifact into the draft directory. The original
23
+ `brief.md` stays preserved as the campaign thesis input.
24
+ </objective>
25
+
26
+ <files>
27
+
28
+ Validated draft directory:
29
+
30
+ ```text
31
+ .sellable/create-campaign-v2/drafts/{workspace-slug}/{campaign-slug}/
32
+ brief.md
33
+ lead-review.md
34
+ lead-sample.json
35
+ lead-filter.md
36
+ message-validation.md
37
+ rubric.json # optional implementation artifact only
38
+ ```
39
+
40
+ </files>
41
+
42
+ <rules>
43
+
44
+ - `brief.md` is the stable Phase 83 input and remains the thesis source.
45
+ - `lead-review.md` and `lead-sample.json` are the required outputs of `find leads`.
46
+ - `lead-filter.md` is the primary output of `filter leads`.
47
+ - `rubric.json` is optional and secondary to `lead-filter.md`.
48
+ - `message-validation.md` is the output of `generate message`.
49
+ - Run validation serially in this order: `find leads`, `filter leads`, `generate message`.
50
+ - Resume state is based on the presence and completeness of the chained artifacts,
51
+ not on inline validation blocks inside `brief.md`.
52
+ - Preserve the Phase 83 thesis. Do not rewrite product, ICP, offer, or message
53
+ hypothesis sections during preview validation.
54
+ - Every artifact write uses `tmp + rename` so a failed write leaves the prior
55
+ artifact intact.
56
+ - If a required upstream artifact is missing, stop and route back to the
57
+ missing step instead of guessing.
58
+
59
+ </rules>
60
+
61
+ <step_contracts>
62
+
63
+ ## Step 1: Find Leads
64
+
65
+ Use existing `find-leads` campaignless preview behavior to validate ICP and
66
+ volume with a real sample.
67
+
68
+ Write:
69
+
70
+ - `lead-review.md`
71
+ - `lead-sample.json`
72
+
73
+ Required behavior:
74
+
75
+ - use campaignless preview mode
76
+ - do not pass `campaignOfferId`
77
+ - do not import leads
78
+ - do not set `selectedLeadListId`
79
+ - do not create lead-list rows
80
+ - do not mutate DB-backed campaign state
81
+ - do not use generic tool discovery when the MCP tool names are already known
82
+ - start with the narrowest credible role/company TAM for the first lane, then inspect a real sample before deciding the lane is good enough
83
+ - after the first real search, estimate projected good fits from the sample and surface the math explicitly
84
+ - if the projected good-fit pool is below roughly 300 and the market is not clearly niche by brief design, run one more real refinement or widening search before finalizing
85
+ - if the market is clearly niche by brief design, it is acceptable to confirm a smaller pool, but say explicitly that it is niche-limited and still large enough for the first campaign
86
+ - if the brief's primary goal is to reach out to people most likely to reply and the TAM plausibly uses LinkedIn, test a Signals-first lane before defaulting to Sales Nav
87
+ - for reply-likelihood-first outbound, use this fallback order unless the brief explicitly points elsewhere: `Signals -> Sales Nav -> Prospeo`
88
+ - if the Signals lane is too sparse, too noisy, or too small to sustain the campaign, say that explicitly and fall back to Sales Nav rather than forcing it
89
+ - if the brief's primary channel is InMail or LinkedIn send, test a `POSTED_ON_LINKEDIN` slice after the baseline TAM whenever that slice can still support the first campaign
90
+ - for InMail / LinkedIn send lanes, prefer the recently-posted slice as the first-send segment when it still yields enough projected good fits; if it is too small, explicitly remove the posted filter and continue with the non-posted role/company/industry lane
91
+ - use Prospeo as the fallback when Signals and Sales Nav still cannot produce enough good fits or when account/domain expansion is the clearest next move
92
+ - when a provider response includes reusable search URLs, include only one plain-English link label in `lead-review.md` such as `Search link I'd use:` so the user can open the search we actually want to use; mention discarded searches in prose without extra links and avoid internal phrasing like `chosen lane`
93
+ - for regulated bank fraud / AML briefs, start title-first and Banking-first on the first sweep; do not begin with broad bio-keyword searches across generic Financial Services
94
+ - treat card networks, payments platforms, insurers, asset managers, vendors, and generic transformation / analytics roles as second-pass expansions only after the title-first Banking lane is tested
95
+ - for retail CPG brand ops briefs, start with brand-side ops-owner titles first and prefer finished-goods industries such as Food and Beverage Manufacturing, Beverage Manufacturing, and Personal Care Product Manufacturing before broad Consumer Goods
96
+ - for retail CPG brand ops briefs, treat suppliers, CDMOs, packaging, logistics / 3PLs, retailers, and service companies as false positives unless the brief explicitly targets them
97
+ - for retail CPG brand ops briefs, widen headcount before widening industry when the first pass is clean but small, and prefer named-account / domain-list second passes over generic industry expansion
98
+
99
+ `lead-review.md` must state:
100
+
101
+ - validation status: `confirmed`, `rejected`, or `unclear`
102
+ - confidence
103
+ - provider path used
104
+ - plain-English search link label when available (for example `Search link I'd use`)
105
+ - preview count
106
+ - ICP match rate
107
+ - sampledCount
108
+ - passCount
109
+ - passRate
110
+ - projectedGoodFits
111
+ - expectedPostFilterRange
112
+ - volume comparison
113
+ - repeated false-positive patterns
114
+ - suggested next action or revision
115
+
116
+ `lead-sample.json` must be a machine-readable sample that downstream filter
117
+ validation can inspect directly.
118
+
119
+ If preview returns zero usable leads, write the rejection evidence, stop the
120
+ chain, and route to `revise-leads`.
121
+
122
+ ## Step 2: Filter Leads
123
+
124
+ Read `brief.md`, `lead-review.md`, and `lead-sample.json`.
125
+
126
+ Write:
127
+
128
+ - `lead-filter.md`
129
+ - optional `rubric.json`
130
+
131
+ Required behavior:
132
+
133
+ - preserve recurring keep/exclude filter families that show up across campaign
134
+ history: buyer role, wrong-function exclusions, company-type exclusions,
135
+ competitor/vendor exclusions, geography, company size, and active-role status
136
+ - use the actual lead sample to identify repeated false positives
137
+ - prefer required keep/exclude rules over a broad scoring stack
138
+ - allow at most one optional/supporting rule when it materially helps later
139
+ messaging or prioritization
140
+ - judge each proposed rule against the sample, report pass rate, and call out
141
+ whether the rule is truly necessary or should be removed
142
+ - make every accepted filter directly translatable into production
143
+ `LeadScoringRubric` rows (`checkName`, `description`, `criterion`, `reason`,
144
+ `isRequiredCheck`, `allowPartialCredit`, `strictMatching`)
145
+ - do not accept a filter that cannot be evaluated from `lead-sample.json`,
146
+ provider row fields, enrichment, or normal public research
147
+ - derive `rubric.json` from the final `lead-filter.md` rules only when a
148
+ machine-readable sidecar is needed downstream
149
+ - continue with `lead-filter.md` as the source of truth when `rubric.json`
150
+ cannot be written or parsed
151
+ - if `rubric.json` is omitted, keep the filter concise enough that a 2-5 item
152
+ production rubric can be compiled from it without inventing new rules
153
+ - write `lead-filter.md` user-facing first: decision, who we keep, who we
154
+ exclude, what the sample showed, pass rate, recommendation
155
+ - include `Implementation Details` inside `lead-filter.md` whenever the status
156
+ is confirmed; this is where production rubric fields belong
157
+ - `Implementation Details` must be a fenced JSON object with
158
+ `leadScoringRubrics` so downstream can parse/save the rules without
159
+ inference
160
+
161
+ `lead-filter.md` must contain:
162
+
163
+ - `Status`
164
+ - `Decision`
165
+ - `Who We'll Keep`
166
+ - `Who We'll Exclude`
167
+ - `Sample False Positives`
168
+ - `Optional Supporting Rule` only when one is clearly justified
169
+ - `Pass Rate`
170
+ - `Recommendation`
171
+ - `Implementation Details`
172
+
173
+ When `rubric.json` is emitted, it must use the production rubric shape, not a
174
+ custom sidecar schema:
175
+
176
+ - `leadScoringRubrics`
177
+ - `checkName`
178
+ - `description`
179
+ - `criterion`
180
+ - `reason`
181
+ - `isRequiredCheck`
182
+ - `allowPartialCredit`
183
+ - `strictMatching`
184
+
185
+ `Implementation Details` must contain a fenced JSON object with
186
+ `leadScoringRubrics`, and that array must contain 2-5 production rubric items
187
+ total. Do not create one rubric row per keep/exclude bullet. Bundle related
188
+ false-positive families into one exclusion criterion, and keep role fit as its
189
+ own explicit criterion. Keep raw rubric flags out of the top user-facing
190
+ sections.
191
+
192
+ Do not:
193
+
194
+ - call `check_rubric`
195
+ - call `save_rubrics`
196
+ - create a second independent scoring design in `rubric.json`
197
+ - emit more than one optional/supporting rule
198
+
199
+ ## Step 3: Generate Message
200
+
201
+ Read `brief.md`, `lead-filter.md`, and `lead-sample.json`.
202
+
203
+ Write:
204
+
205
+ - `message-validation.md`
206
+
207
+ Run the `generate-messages` skill in caller-declared `DRY MODE`. Its SKILL.md
208
+ holds the full drafting contract (retrieval, proof inventory, candidates,
209
+ finalizer pass, voice rules, safety). This step only covers orchestration.
210
+
211
+ Orchestration requirements:
212
+
213
+ - draft only after real leads and final filter rules exist
214
+ - pass no `campaignId`
215
+ - read only `brief.md`, `lead-filter.md`, `lead-sample.json`, and the
216
+ `gold-standard-*` references
217
+ - generate 2-3 sample messages inline
218
+ - start output with `Mode: DRY MODE (no DB mutation)`
219
+ - treat the archived examples as the **quality bar**, not a paste source;
220
+ write messages that could plausibly belong in the archive for this motion
221
+ - exact-template preservation only applies when the archived winner is the
222
+ same company as the brief
223
+ - draft 3 internal candidates and run a Finalizer Pass that combines the
224
+ best opener, proof sentence, bridge, and CTA across them into one winner
225
+ - pass the Thomas revision filters before writing findings
226
+
227
+ Do not:
228
+
229
+ - call `get_campaign`
230
+ - call `get_rows`
231
+ - call `update_cell`
232
+ - call `update_campaign_brief`
233
+ - fetch fresh web or LinkedIn research
234
+ - mutate DB-backed campaign state
235
+
236
+ `message-validation.md` must contain:
237
+
238
+ - `Status`
239
+ - `Mode`
240
+ - `Template Used`
241
+ - `Primary Example`
242
+ - `Secondary Influence`
243
+ - `Lead Sample Basis`
244
+ - `Strongest Reply Reason`
245
+ - `Pre-Draft Buyer-Role Analysis`
246
+ - `Campaign Element Pool`
247
+ - `Gold Standard Strategy Map`
248
+ - `Current Campaign Translation`
249
+ - `Element Scoring`
250
+ - `Proof Inventory`
251
+ - `Token Fill Rules`
252
+ - `Token Adherence Table`
253
+ - `Angle Drafts`
254
+ - `Kill / Combine Review`
255
+ - `Finalists`
256
+ - `Candidate Messages`
257
+ - `Finalizer Pass`
258
+ - `Gold-Standard Quality Gate`
259
+ - `Skeptical Prospect Review`
260
+ - `Winner Gate`
261
+ - `Selected Winner`
262
+ - `Findings`
263
+ - `Recommendation`
264
+
265
+ If token sourcing is weak, revise token fill rules or route back to
266
+ `revise-filter` or `revise-message` instead of guessing.
267
+
268
+ </step_contracts>
269
+
270
+ <resume_rules>
271
+
272
+ - Only `brief.md` present -> run `find leads`
273
+ - `lead-review.md` + `lead-sample.json` present, but no `lead-filter.md` -> run
274
+ `filter leads`
275
+ - `lead-filter.md` present, but no `message-validation.md` -> run `generate message`
276
+ - `message-validation.md` present -> validation is complete
277
+ - `lead-review.md` without `lead-sample.json`, or vice versa -> stop with a
278
+ contract violation
279
+ - `lead-filter.md` without upstream lead artifacts -> stop with a contract violation
280
+
281
+ </resume_rules>
282
+
283
+ <boundaries>
284
+
285
+ Do not create live campaign state.
286
+
287
+ Do not:
288
+
289
+ - mint a campaign
290
+ - import leads
291
+ - persist selected lead lists
292
+ - attach downstream assets
293
+ - save remote rubric state
294
+ - move the user into a live execution step
295
+
296
+ </boundaries>