@sellable/mcp 0.1.136 → 0.1.138
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/agents/post-find-leads-filter-scout.md +19 -25
- package/agents/post-find-leads-message-scout.md +21 -0
- package/agents/registry.json +9 -16
- package/agents/source-scout-linkedin-engagement.md +2 -2
- package/dist/engage-memory.d.ts +13 -0
- package/dist/engage-memory.js +129 -34
- package/dist/identity-compiler.d.ts +119 -0
- package/dist/identity-compiler.js +344 -0
- package/dist/identity-memory.d.ts +49 -0
- package/dist/identity-memory.js +89 -0
- package/dist/index-dev.js +0 -0
- package/dist/index.js +0 -0
- package/dist/tools/bootstrap.js +1 -1
- package/dist/tools/engage-memory.js +2 -2
- package/dist/tools/navigation.js +3 -0
- package/dist/tools/prompts.d.ts +1 -4
- package/dist/tools/prompts.js +3 -3
- package/package.json +1 -1
- package/skills/craft-message/SKILL.md +13 -4
- package/skills/create-campaign/references/brief-template.md +2 -1
- package/skills/create-campaign-v2/SKILL.md +150 -1342
- package/skills/create-campaign-v2/core/flow.v2.json +471 -1970
- package/skills/create-post/SKILL.md +54 -9
- package/skills/engage/SKILL.md +37 -15
- package/skills/engage/core/README.md +18 -12
- package/skills/generate-messages/SKILL.md +15 -5
- package/skills/interview/SKILL.md +183 -89
- package/skills/interview/references/anti-ai-audit.md +101 -0
- package/skills/interview/references/compiler-schema.md +94 -0
- package/skills/interview/references/legacy-linkedin-interview.md +118 -0
- package/skills/interview/references/question-bank.md +123 -0
- package/skills/interview/references/reference-curation.md +68 -0
- package/skills/interview/references/voice-capture-method.md +62 -0
|
@@ -1,1385 +1,193 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: create-campaign-v2
|
|
3
|
-
description: Execute the JSON-gated shell-first campaign flow
|
|
3
|
+
description: Execute the compact JSON-gated shell-first campaign flow: resolve campaign identity, create a watchable CampaignOffer shell with the brief, attach and approve the source, import the bounded review batch, persist rubrics and approved message template, validate the review batch, then hand off to Settings, sequence, and start.
|
|
4
4
|
visibility: internal
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Create Campaign v2
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
user, resolve campaign identity/client-prospect context, and create a watchable
|
|
13
|
-
campaign shell with the v1 brief already attached, (2) use that campaign id for
|
|
14
|
-
source selection, (3) import/confirm the first 15-row review batch to establish
|
|
15
|
-
`workflowTableId`, (4) create rubrics and message artifacts from that campaign
|
|
16
|
-
table sample, (5) sync the approved message set into the campaign brief, and
|
|
17
|
-
(6) queue/observe the bounded cascade before settings, sequence, and start.
|
|
18
|
-
</role>
|
|
9
|
+
You are the create-campaign-v2 orchestrator. Run the active state machine in
|
|
10
|
+
`core/flow.v2.json`; load deeper references only at the stage that needs them.
|
|
11
|
+
This prompt is the fast entry point, not the full workflow manual.
|
|
19
12
|
|
|
20
|
-
|
|
21
|
-
Run the configured JSON flow in durable stages:
|
|
22
|
-
|
|
23
|
-
0. client identity/source intake + watchable campaign shell with v1 brief
|
|
24
|
-
1. create-campaign-brief
|
|
25
|
-
2. find leads with the campaign id
|
|
26
|
-
3. import/confirm the first 15-row review batch
|
|
27
|
-
4. filter leads from the campaign table sample
|
|
28
|
-
5. generate message from the same campaign table sample
|
|
29
|
-
6. message review gate
|
|
30
|
-
7. sync approved message set into the campaign brief
|
|
31
|
-
8. queue and validate the 15-row cascade
|
|
32
|
-
9. settings/sender, sequence, and start handoff
|
|
33
|
-
|
|
34
|
-
The JSON flow is the source of truth for stage order, artifact policy,
|
|
35
|
-
`requiredArtifacts`, `producesArtifacts`, `allowedTools`, `doNotAllow`,
|
|
36
|
-
`waitFor`, and `transitions`. In normal customer runs, obey
|
|
37
|
-
`artifactPolicy.normalCustomerPath`: use campaign state and MCP responses instead
|
|
38
|
-
of local draft files. This prompt explains how to execute those gates; it does
|
|
39
|
-
not replace them.
|
|
40
|
-
|
|
41
|
-
CampaignOffer state and the watch link are the customer-facing source of truth.
|
|
42
|
-
Disk artifacts are optional debug/UAT diagnostics only. In normal customer runs,
|
|
43
|
-
do not create, link, or surface local draft files unless the user explicitly asks
|
|
44
|
-
for debug artifacts or the run is an explicit UAT/rehearsal. Resume, gating, and
|
|
45
|
-
handoff read campaign state first: campaign id, watch URL, campaign brief,
|
|
46
|
-
currentStep, provider/search association, selectedLeadListId as the source
|
|
47
|
-
list, workflowTableId as the campaign table, saved rubrics, approved message
|
|
48
|
-
template, senderIds, sequence template, and running state.
|
|
49
|
-
|
|
50
|
-
There is no separate approval-packet, commit-gate, or mint step in the active
|
|
51
|
-
shell-first flow. The campaign exists early for watch mode. The hard boundary
|
|
52
|
-
is import/enrichment: no leads are imported, no workflow cells are queued, no
|
|
53
|
-
sequence is attached, and nothing starts until the source is selected, filter
|
|
54
|
-
choice is resolved, rubrics are saved when filters are enabled, and Messages
|
|
55
|
-
has either approved template/token rules or selected the product's AI-generated
|
|
56
|
-
path.
|
|
57
|
-
</objective>
|
|
58
|
-
|
|
59
|
-
<files>
|
|
60
|
-
|
|
61
|
-
Optional debug/UAT draft directory, disabled in normal customer runs:
|
|
13
|
+
Load the compact flow when you need exact gates:
|
|
62
14
|
|
|
63
15
|
```text
|
|
64
|
-
|
|
65
|
-
brief.md
|
|
66
|
-
campaign-shell.json # debug copy of the watchable campaign shell with v1 brief
|
|
67
|
-
lead-review.md
|
|
68
|
-
lead-sample.json
|
|
69
|
-
lead-filter.md
|
|
70
|
-
message-prep.md # optional speed artifact
|
|
71
|
-
message-candidate-drafts.md # optional provisional message artifact
|
|
72
|
-
message-validation.md
|
|
73
|
-
message-review.md
|
|
74
|
-
message-review-decision.md
|
|
75
|
-
rubric.json # optional implementation artifact only
|
|
76
|
-
approval-packet.md # legacy/deprecated only
|
|
77
|
-
customer-roleplay.md
|
|
78
|
-
commit-gate-decision.md # legacy/deprecated only
|
|
16
|
+
get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "core/flow.v2.json" })
|
|
79
17
|
```
|
|
80
18
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<rules>
|
|
84
|
-
|
|
85
|
-
- Net-new runs start at `bootstrap` -> `brief-interview` in
|
|
86
|
-
`core/flow.v2.json`. Do not start at `validate-artifacts` unless resuming a
|
|
87
|
-
compatibility run where all upstream artifacts already exist.
|
|
88
|
-
- New runs create a watchable campaign shell after campaign identity/client
|
|
89
|
-
prospect context, campaign focus, source intake, and the v1 brief are known.
|
|
90
|
-
The shell is a
|
|
91
|
-
`CampaignOffer` at `currentStep: "create-offer"` with a real v1 brief and a
|
|
92
|
-
`watchUrl`; when the user opens it they should see the brief, not an empty
|
|
93
|
-
campaign. If shell creation fails, stop and surface the error. There is no
|
|
94
|
-
no-shell mint fallback in the active shell-first flow.
|
|
95
|
-
- The main thread owns watch navigation. Before expensive work in each major
|
|
96
|
-
stage, call `update_campaign({ campaignId, currentStep, watchNarration })`
|
|
97
|
-
with the visible UI step the user should be watching, then continue the work
|
|
98
|
-
from MCP/product state. Every currentStep switch in a watched run must refresh
|
|
99
|
-
`watchNarration` in the same visible beat. The copy must say what just
|
|
100
|
-
happened, what the browser is showing now, what Codex is doing next, and what
|
|
101
|
-
the user should do next. Use `create-offer` for the brief, `pick-provider` or
|
|
102
|
-
the selected provider step while sourcing, `filter-choice` after the 15-row
|
|
103
|
-
review batch is imported, `apply-icp-rubric` while template approval is
|
|
104
|
-
pending on Filter Leads, `auto-execute-messaging` for approved message work,
|
|
105
|
-
`awaiting-user-greenlight` for Settings, and `validate-sample` only for
|
|
106
|
-
recovery/legacy validation if reached. Do not advance `currentStep` backward.
|
|
107
|
-
- After the shell is minted, normal resume paths read the CampaignOffer first.
|
|
108
|
-
Use debug files to explain or reconstruct work, not to decide whether a
|
|
109
|
-
post-mint gate is allowed. validation/debug artifacts are not durable campaign
|
|
110
|
-
state.
|
|
111
|
-
- The campaign shell may receive setup state before import: approved brief text,
|
|
112
|
-
campaign-attached provider searches/selections, the bounded review-batch
|
|
113
|
-
import, saved rubrics, and the approved message template. It must never queue
|
|
114
|
-
workflow cells, attach a sequence, or start sending until rubrics are saved
|
|
115
|
-
and the approved message set has been synced into the campaign brief.
|
|
116
|
-
- Sender ownership belongs only to the final Settings handoff after message
|
|
117
|
-
validation. At that point the main thread may ask the user to connect or
|
|
118
|
-
select a LinkedIn sender, explain Slack reply review before launch, attach the
|
|
119
|
-
selected sender with `update_campaign({ senderIds, currentStep: "sequence" })`,
|
|
120
|
-
attach the recommended sequence, then move the watched UI to Send. It still
|
|
121
|
-
must not start sending until the user explicitly greenlights launch.
|
|
122
|
-
- senderIds persistence uses `update_campaign({ senderIds })`, which delegates
|
|
123
|
-
to the v3 senders route and never uses the v2 campaign-offers PUT for sender
|
|
124
|
-
persistence.
|
|
125
|
-
- Load `core/flow.v2.json` through
|
|
126
|
-
`get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "core/flow.v2.json" })`
|
|
127
|
-
at the start of the run and treat the returned JSON as the active state
|
|
128
|
-
machine. Do not read repo-local config files; packaged Claude Code and Codex
|
|
129
|
-
runs must use the MCP asset loader so they execute the same workflow.
|
|
130
|
-
- Use the host-native structured question gate whenever it is exposed. In
|
|
131
|
-
Claude Code, this is `AskUserQuestion`. In Codex, this is
|
|
132
|
-
`request_user_input` (enabled in Default mode by
|
|
133
|
-
`[features].default_mode_request_user_input = true`, not available in
|
|
134
|
-
`codex exec`). Treat them as equivalent approval/intake gates and persist the
|
|
135
|
-
same campaign state after the user answers. Use this structured gate only for
|
|
136
|
-
single-choice decisions with fixed options or approval gates. Every campaign
|
|
137
|
-
setup gate must be single-choice in both hosts: set or assume
|
|
138
|
-
`multiSelect: false`, use mutually exclusive option labels, and do not ask
|
|
139
|
-
for checkbox or multi-select answers. If a blended answer is useful, present
|
|
140
|
-
the blend as one explicit option or route the user through `Other / custom`
|
|
141
|
-
and a free-text follow-up in chat. Never use it to collect open text input
|
|
142
|
-
like LinkedIn URLs, company domains, notes, pasted context, campaign ideas,
|
|
143
|
-
or feedback. For open text, ask in normal chat and wait for the user to paste
|
|
144
|
-
the value. If an interactive
|
|
145
|
-
Codex session does not expose `request_user_input`, do not silently degrade to
|
|
146
|
-
a plain chat question; stop and tell the user:
|
|
147
|
-
|
|
148
|
-
```text
|
|
149
|
-
I need Codex’s quick question panel to collect campaign inputs and approvals cleanly.
|
|
150
|
-
|
|
151
|
-
It isn’t enabled in this Codex session yet. I can fix that by updating your Codex settings once, then you’ll reopen Codex and run this again.
|
|
152
|
-
|
|
153
|
-
Can I update your Codex settings so Sellable can use the quick question panel?
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
If they approve, update `~/.codex/config.toml` so
|
|
157
|
-
`[features].default_mode_request_user_input = true`, then tell them:
|
|
158
|
-
|
|
159
|
-
```text
|
|
160
|
-
Done. Please fully quit and reopen Codex, then run:
|
|
161
|
-
|
|
162
|
-
$sellable:create-campaign
|
|
163
|
-
|
|
164
|
-
After that, I’ll confirm who we’re launching for, then ask the setup questions
|
|
165
|
-
and start the campaign brief.
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
If they decline, tell them to switch to Plan/collaboration mode and rerun
|
|
169
|
-
`$sellable:create-campaign`. In
|
|
170
|
-
non-interactive `codex exec`, structured user input is unavailable by design;
|
|
171
|
-
ask in chat only when the run is explicitly a non-interactive smoke/rehearsal.
|
|
172
|
-
|
|
173
|
-
- Customer-facing progress updates must use product language. Say "quick
|
|
174
|
-
setup choices", "campaign brief", "Find Leads", and "approval" instead of
|
|
175
|
-
`request_user_input`, Default mode, MCP namespaces, plugin caches, prompt
|
|
176
|
-
loading, runbooks, local skill files, skill versions, npm/package details,
|
|
177
|
-
repo-local files, VPS/off-desktop/browser automation limitations, or
|
|
178
|
-
"Sellable token".
|
|
179
|
-
"Quick question panel" is only acceptable when explaining a Codex/Claude setup
|
|
180
|
-
blocker.
|
|
181
|
-
- Before the 15-lead import/test batch, do not call `check_rubric`; Phase 84
|
|
182
|
-
only writes and validates artifacts, saves rubrics, and syncs campaign setup
|
|
183
|
-
state.
|
|
184
|
-
- Never narrate local draft housekeeping to the user. If you create directories,
|
|
185
|
-
save drafts, write artifacts, or persist intermediate state, translate it into
|
|
186
|
-
the campaign benefit: consistent brief, approved lead source, reviewed message,
|
|
187
|
-
or safe launch. Do not say "persist", "local draft folder", "artifact",
|
|
188
|
-
"mkdir", "campaign thesis", or "same approved campaign thesis" in
|
|
189
|
-
customer-facing progress copy.
|
|
190
|
-
- Watch guide copy must use the single `watchNarration` object whenever you set
|
|
191
|
-
`currentStep` or report visible progress in a watched run. Read
|
|
192
|
-
`references/watch-guide-narration.md` for the compact screen contract. Do not
|
|
193
|
-
send separate guide headline/body args. In Find Leads, the static stage label
|
|
194
|
-
is not enough: name the active lane/provider, what search or sample you are
|
|
195
|
-
trying, and why it fits this campaign. When the source recommendation and
|
|
196
|
-
counts/sample quality are ready in chat, update the guide to tell the user to
|
|
197
|
-
review and approve the source in Codex/Claude instead of saying `I'll show`
|
|
198
|
-
the recommendation later. Do not promise time estimates in guide copy.
|
|
199
|
-
- Every approval gate must include live campaign access after the readable inline
|
|
200
|
-
content. Show a short `Watch link:` line with the campaign link when a
|
|
201
|
-
campaign shell exists. In normal customer runs, do not show `Open artifact:`
|
|
202
|
-
lines, raw filesystem paths, or local draft filenames. If the run is explicit
|
|
203
|
-
debug/UAT or the user asks for local artifacts, artifact links may be shown as
|
|
204
|
-
secondary diagnostics. The link is never a substitute for rendering the
|
|
205
|
-
decision in chat.
|
|
206
|
-
- Any time the user is reviewing a list or decision, use rendered Markdown with
|
|
207
|
-
short indexed sections and bullets. Do not use label-plus-paragraph blocks
|
|
208
|
-
like `Key numbers:` followed by one long paragraph. Do not use fenced code
|
|
209
|
-
blocks for review surfaces.
|
|
210
|
-
- Do not treat the active Sellable workspace as the campaign subject. The
|
|
211
|
-
workspace only tells you where the campaign will be saved. Before buyer, CTA,
|
|
212
|
-
proof, or source questions, identify the campaign identity: the person/profile
|
|
213
|
-
or company this campaign is for, plus enough company/product context to build
|
|
214
|
-
the brief. This is only the client-prospect/bootstrap identity for
|
|
215
|
-
`clientProspectId` or `senderLinkedinUrl`; it is not a connected-sender check.
|
|
216
|
-
- Do not call `list_senders`, `get_sender`, or surface connected/missing sender
|
|
217
|
-
state during setup, brief, source, filter, or message review. Sender
|
|
218
|
-
availability belongs only to the Settings/final launch handoff after
|
|
219
|
-
`approve-message` and the 15-lead validation sample. The first user-visible
|
|
220
|
-
sender blocker should be at `awaiting-user-greenlight`/Settings.
|
|
221
|
-
- If the invocation or user answer includes an existing `clientProspectId`, keep
|
|
222
|
-
it as the preferred `create_campaign` identity input. If it includes a
|
|
223
|
-
LinkedIn profile URL, keep that URL as `senderLinkedinUrl` so the backend can
|
|
224
|
-
resolve/materialize the sender prospect when the watchable campaign shell is
|
|
225
|
-
created. Do not pass a LinkedIn company page as `senderLinkedinUrl`; for a
|
|
226
|
-
company-only identity, use `clientProspectId` if already materialized or do
|
|
227
|
-
one lightweight lookup to find the relevant founder/operator profile. Do not
|
|
228
|
-
require a connected sender before shell creation.
|
|
229
|
-
- If the user supplied a LinkedIn profile, website, domain, company name, or
|
|
230
|
-
explicit client prospect identity in the invocation, do one lightweight lookup
|
|
231
|
-
first:
|
|
232
|
-
- LinkedIn profile: call `fetch_linkedin_profile`.
|
|
233
|
-
- Website/domain/company: call `fetch_company` when possible, otherwise one
|
|
234
|
-
web lookup.
|
|
235
|
-
- Existing client prospect id: use it directly and do one company/profile
|
|
236
|
-
lookup only if a URL/domain is also available.
|
|
237
|
-
Then summarize what you found in one or two lines and ask the user to confirm
|
|
238
|
-
the campaign identity/focus before continuing. Do not mention connected sender
|
|
239
|
-
availability in this confirmation.
|
|
240
|
-
- If the user did not provide the launch identity, ask in normal chat for the
|
|
241
|
-
LinkedIn profile or company website to use as the campaign identity. Do not ask
|
|
242
|
-
them to choose an input type with the structured question tool:
|
|
243
|
-
|
|
244
|
-
```text
|
|
245
|
-
I’m ready to build this in {workspace}.
|
|
246
|
-
|
|
247
|
-
First, paste the LinkedIn profile or company website for the client/company
|
|
248
|
-
this campaign is for. I’ll use that to resolve the campaign identity before we
|
|
249
|
-
choose the target, offer, proof, and lead source.
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn
|
|
253
|
-
profile, call `fetch_linkedin_profile` and infer the current or most recent
|
|
254
|
-
company from the profile. For a company website, call `fetch_company` when
|
|
255
|
-
possible, otherwise one web lookup. If a LinkedIn profile URL is available,
|
|
256
|
-
retain it as `senderLinkedinUrl` for `create_campaign`; if only a LinkedIn
|
|
257
|
-
company page is available, do not pass it as `senderLinkedinUrl`. If a
|
|
258
|
-
`clientProspectId` is available, pass that instead.
|
|
259
|
-
|
|
260
|
-
Sufficient-intake bypass: when the invocation or first operator answer already
|
|
261
|
-
supplies identity/client context, target prospects, offer/CTA, proof guidance,
|
|
262
|
-
and lead-source preference or permission to find people, do not ask the setup
|
|
263
|
-
packet again. Do one lightweight lookup, state the inferred campaign direction
|
|
264
|
-
in one or two lines, and move directly into the campaign brief. Ask only when a
|
|
265
|
-
required field is missing, the supplied inputs conflict, or the campaign focus
|
|
266
|
-
is genuinely ambiguous. The brief approval gate is the correction point for
|
|
267
|
-
inferred assumptions.
|
|
268
|
-
|
|
269
|
-
After the user confirms the campaign identity, check whether the company
|
|
270
|
-
context implies more than one campaignable product line, service, or offer.
|
|
271
|
-
If so, ask one structured campaign-focus question before the setup packet
|
|
272
|
-
(for example, "Which Sellable offer is this campaign for?") with no more than
|
|
273
|
-
three specific options plus `Other / custom`. Do not ask this as plain
|
|
274
|
-
numbered chat.
|
|
275
|
-
|
|
276
|
-
Then run one lightweight campaign identity research pass before campaign
|
|
277
|
-
shell creation. The legacy subskill/tool names are `research-sender` and
|
|
278
|
-
`complete_sender_research`, but treat them as client/company prospect research
|
|
279
|
-
for the campaign, not as a connected-sender availability check. Prefer loading
|
|
280
|
-
`get_subskill_prompt({ subskillName: "research-sender" })`, running its
|
|
281
|
-
fetch/profile/company/WebSearch batch when those tools are exposed, and
|
|
282
|
-
calling `complete_sender_research`. If WebSearch is unavailable, use the
|
|
283
|
-
available MCP profile/company/post tools, call `complete_sender_research`
|
|
284
|
-
with the evidence counts found, and continue with explicit gaps. Setup
|
|
285
|
-
questions and the campaign brief should use the confirmed company context and
|
|
286
|
-
researched proof / positioning options so they do not feel generic. If
|
|
287
|
-
identity is still unavailable, use neutral/custom intake options instead of
|
|
288
|
-
guessed vertical-specific options.
|
|
289
|
-
|
|
290
|
-
- Before the identity gate, use this customer-facing shape:
|
|
291
|
-
|
|
292
|
-
```text
|
|
293
|
-
I’m ready to build the campaign in {workspace}.
|
|
294
|
-
|
|
295
|
-
First I’ll resolve the client/company this campaign is for. I’ll use that
|
|
296
|
-
context to choose the target, offer, proof, and lead source.
|
|
297
|
-
|
|
298
|
-
Then I’ll turn that into a campaign brief for you to approve before any leads
|
|
299
|
-
are imported or anything can send.
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
- Fast Intake Mode is mandatory for hosted/rehearsal net-new runs. Ask the
|
|
303
|
-
first founder strategy/source question packet in under 60 seconds. Before
|
|
304
|
-
that first packet, the first assistant turn may only call
|
|
305
|
-
`bootstrap_create_campaign`, load this workflow prompt with
|
|
306
|
-
`get_subskill_prompt({ subskillName: "create-campaign-v2" })`, optionally run
|
|
307
|
-
one lightweight identity lookup, then use the structured question gate. If the user
|
|
308
|
-
supplied a company website/domain, call exactly one of `fetch_company`,
|
|
309
|
-
`WebFetch`, or `WebSearch` to identify what the company actually does before
|
|
310
|
-
generating setup options. If the user supplied a LinkedIn profile URL, call
|
|
311
|
-
`fetch_linkedin_profile` before generating setup options. Do not infer the
|
|
312
|
-
product category from the company name alone. If no domain, website, LinkedIn
|
|
313
|
-
profile, or client identity is supplied, ask in normal chat for that identity
|
|
314
|
-
before buyer/offer/source. Before the first strategy/source packet,
|
|
315
|
-
`list_senders` is forbidden; sender availability is checked only at Settings.
|
|
316
|
-
Before that first
|
|
317
|
-
structured question gate, do not run source discovery, Sales Nav, Prospeo,
|
|
318
|
-
Signals, Bash, Read, Write, Edit, Glob, Grep, full company research, or
|
|
319
|
-
draft-directory inspection/creation. In normal customer runs, do not create a
|
|
320
|
-
draft directory after the founder answers; create/update the campaign shell and
|
|
321
|
-
campaign state instead. After launch identity and any ambiguous campaign focus are
|
|
322
|
-
confirmed, the setup packet must
|
|
323
|
-
use the structured question gate and ask buyer, offer/CTA, proof, and lead
|
|
324
|
-
source. All four questions must include an `Other / custom` option.
|
|
325
|
-
Exception: if the initial request already satisfies the sufficient-intake
|
|
326
|
-
bypass above, skip the setup packet and draft the brief from the supplied
|
|
327
|
-
context. Do not ask first-turn setup questions just to restate choices the
|
|
328
|
-
operator already provided.
|
|
329
|
-
- After the founder answers the first strategy/source packet, explain the next
|
|
330
|
-
stage only: campaign brief creation and brief approval. Use this shape:
|
|
331
|
-
|
|
332
|
-
```text
|
|
333
|
-
Got it. I'll turn this into a campaign brief first (~1-2 min), then show it to you so you can approve it or tell me what to change before I source leads.
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
If local draft setup or artifact writing happens next, keep that silent or
|
|
337
|
-
translate it into the brief outcome. Good:
|
|
338
|
-
|
|
339
|
-
```text
|
|
340
|
-
I have enough to draft the campaign brief. I’m turning your answers into the
|
|
341
|
-
positioning, target, offer, and approval checklist now. You’ll see the brief
|
|
342
|
-
before I source any leads.
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
Bad:
|
|
346
|
-
|
|
347
|
-
```text
|
|
348
|
-
I’m going to persist the working brief in the local Sellable draft folder so
|
|
349
|
-
the later lead, filter, and message stages all use the same approved campaign thesis.
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
Do not mention internal artifact names, local folders, shell commands, or
|
|
353
|
-
persistence in this preamble.
|
|
354
|
-
|
|
355
|
-
Before calling `create_campaign` for the watchable shell, make sure the
|
|
356
|
-
campaign identity research marker is satisfied: load `research-sender` if it
|
|
357
|
-
has not already been loaded, do the lightweight profile/company lookup, and
|
|
358
|
-
call `complete_sender_research`. This is still client/company prospect context
|
|
359
|
-
for the campaign brief. Do not call `list_senders`, do not ask the user to
|
|
360
|
-
connect a sender, and do not surface sender availability until
|
|
361
|
-
Settings/final handoff.
|
|
362
|
-
|
|
363
|
-
- Before asking for brief approval, render a slim approval brief in the chat and
|
|
364
|
-
write the rich current brief into `CampaignOffer.campaignBrief` through
|
|
365
|
-
`create_campaign`/`update_campaign`. Use rendered Markdown directly:
|
|
366
|
-
`##` heading, bold field labels, numbered section labels, and short bullets.
|
|
367
|
-
Do not wrap the user-facing approval view in a fenced code block because that
|
|
368
|
-
creates horizontal scrolling in Claude Code and Codex. Do not ask the user to
|
|
369
|
-
approve a one-paragraph direction, a risk note, or hidden artifact they cannot
|
|
370
|
-
inspect. The chat approval view should be skimmable in under 45 seconds; full
|
|
371
|
-
reasoning, source notes, and robustness can stay in optional debug artifacts
|
|
372
|
-
only during explicit debug/UAT runs. Include these sections, with short wrapped
|
|
373
|
-
lines:
|
|
374
|
-
|
|
375
|
-
```text
|
|
376
|
-
## Campaign brief
|
|
377
|
-
|
|
378
|
-
**Decision:** ... (one sentence)
|
|
379
|
-
|
|
380
|
-
**1. Target**
|
|
381
|
-
- ... (include concrete role/title names, not just a broad persona)
|
|
382
|
-
- ...
|
|
383
|
-
|
|
384
|
-
**2. Pain**
|
|
385
|
-
- ...
|
|
386
|
-
- ...
|
|
387
|
-
|
|
388
|
-
**3. Offer**
|
|
389
|
-
- ...
|
|
390
|
-
- ...
|
|
391
|
-
|
|
392
|
-
**4. Proof**
|
|
393
|
-
- ...
|
|
394
|
-
- ...
|
|
395
|
-
|
|
396
|
-
**5. Lead plan**
|
|
397
|
-
I’ll look for people who are already showing signs this problem matters:
|
|
398
|
-
- people talking about ...
|
|
399
|
-
- people with roles like ...
|
|
400
|
-
- companies likely to feel ...
|
|
401
|
-
|
|
402
|
-
If that pool is too small or noisy, I’ll switch to broader LinkedIn title and
|
|
403
|
-
company filters.
|
|
404
|
-
|
|
405
|
-
**6. Risks**
|
|
406
|
-
- ...
|
|
407
|
-
- ...
|
|
408
|
-
|
|
409
|
-
**7. What happens next**
|
|
410
|
-
I’ll find good-fit LinkedIn leads, show the source decision and sample, then
|
|
411
|
-
draft the first message for review. No leads import and nothing sends yet.
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
In the `Lead plan` section, do not expose internal provider shorthand as the
|
|
415
|
-
explanation. Avoid bare phrases like `signal discovery`, `founder-led GTM`,
|
|
416
|
-
`RevOps`, `outbound systems`, or `pipeline architecture` unless they are
|
|
417
|
-
translated into what the user can understand.
|
|
418
|
-
|
|
419
|
-
After rendering that brief, ask for brief approval before Find Leads in
|
|
420
|
-
hosted net-new runs. The user-facing choice should be approve/revise language,
|
|
421
|
-
not "looks good".
|
|
422
|
-
Approval options should refer to what the user just read, e.g. `Approve this
|
|
423
|
-
brief`, `Revise target`, `Revise offer/proof`, and `Other / custom`.
|
|
424
|
-
When the user chose `Find people for me` and the current runtime exposes the
|
|
425
|
-
named Sellable source-scout agents, make the recommended approval label
|
|
426
|
-
explicit: `Approve brief + use background source scouts`. If those agents are
|
|
427
|
-
not visible in this session, use `Approve brief + compare source paths`
|
|
428
|
-
instead. The customer approves the sourcing decision, not the host
|
|
429
|
-
implementation detail.
|
|
430
|
-
Include a `Watch link:` line in the normal chat text immediately before the
|
|
431
|
-
brief approval question once `create_campaign` has returned `watchUrl`. This
|
|
432
|
-
is a hard gate for `AskUserQuestion` / `request_user_input`: do not ask
|
|
433
|
-
`Approve this brief before I start finding leads?` until the user has already
|
|
434
|
-
seen both (1) the full brief content being approved and (2) the watch link for
|
|
435
|
-
the live campaign shell. A summary like `the brief is visible there` is not a
|
|
436
|
-
valid approval surface. If the question panel would appear without the full
|
|
437
|
-
brief and a preceding `Watch link:` line, stop and render those first.
|
|
438
|
-
The visible brief must come before any optional debug persistence. After the
|
|
439
|
-
brief is synthesized, render the approval-ready brief in chat and
|
|
440
|
-
create/update the campaign shell before any visible `mkdir`, `Write`,
|
|
441
|
-
artifact-copy, or similar local draft setup. In normal customer runs, skip
|
|
442
|
-
local draft setup entirely. File/folder creation is not the user's value
|
|
443
|
-
moment; the live campaign brief is.
|
|
444
|
-
|
|
445
|
-
The approval question can be based on the rendered brief in chat and the live
|
|
446
|
-
campaign brief. Do not wait for file-write chrome before asking for approval.
|
|
447
|
-
Before Find Leads, call `update_campaign({ campaignId, campaignBrief,
|
|
448
|
-
currentStep: "pick-provider", watchNarration: { ... } })` after approval so
|
|
449
|
-
the watch link moves out of Plan while the main thread explains the source
|
|
450
|
-
path. This must be a visible Pick Provider checkpoint before the watched
|
|
451
|
-
browser moves into Signal Discovery, Sales Nav, Prospeo, or another provider
|
|
452
|
-
lane.
|
|
453
|
-
|
|
454
|
-
- After the brief is approved, show the next progress line. When the user has
|
|
455
|
-
not given a specific source direction, use the default sequential source
|
|
456
|
-
funnel:
|
|
457
|
-
`Cool. I'm going to find people who are both a good fit and active enough to
|
|
458
|
-
be worth a LinkedIn test. I'll start with people engaging with relevant LinkedIn
|
|
459
|
-
posts because that gives the strongest message context if enough ICP-looking
|
|
460
|
-
people are engaging. If that does not clear a quick viability check, I'll switch
|
|
461
|
-
to Sales Nav to find ICP people actively posting on LinkedIn, then search by
|
|
462
|
-
titles, and use Prospeo for a broader account/contact path. No leads import
|
|
463
|
-
until you approve the source.`
|
|
464
|
-
The watched campaign should still be on Pick Provider while this source logic
|
|
465
|
-
is being explained. If the default first lane is Signal Discovery, say clearly
|
|
466
|
-
that Codex is about to test Signal Discovery as a viability path, not import
|
|
467
|
-
leads: it will look for relevant posts, sample engagers, estimate ICP fit, and
|
|
468
|
-
only continue if the source math works.
|
|
469
|
-
- If the user's request already points to a source, do not force the default
|
|
470
|
-
funnel. Start with the matching lane and say why:
|
|
471
|
-
- specific posts, creators, topics, comments, or engagement signals ->
|
|
472
|
-
Signal Discovery
|
|
473
|
-
- title/persona/company filters or broad LinkedIn people search -> Sales Nav
|
|
474
|
-
- hiring signals, account/domain lists, company growth triggers, email/domain
|
|
475
|
-
search, or target accounts -> Prospeo
|
|
476
|
-
- supplied CSV/profile list -> existing/supplied list preview
|
|
477
|
-
- explicit compare request -> compare only the requested sources
|
|
478
|
-
- In watch mode, do not skip the Pick Provider checkpoint. First move the
|
|
479
|
-
campaign to `pick-provider` and narrate the source-selection reasoning there.
|
|
480
|
-
While the watched browser is still on Pick Provider, ask for approval before
|
|
481
|
-
starting Signal Discovery or a user-directed first lane. After that visible
|
|
482
|
-
checkpoint and approval, move the campaign to the first source lane that will
|
|
483
|
-
actually be tested (`signal-discovery`, `sales-nav`, `prospeo`, or the
|
|
484
|
-
user-directed lane), then run the campaign-attached provider prompt + provider
|
|
485
|
-
search in the parent thread with `campaignOfferId`, `confirmed: true`, and
|
|
486
|
-
`currentStep` when the tool accepts it. If that lane has timeout/error, zero
|
|
487
|
-
raw results, weak ICP fit, or weak message context, update the campaign step
|
|
488
|
-
and watchNarration before trying the next approved lane or ask the user to
|
|
489
|
-
revise the source/target before import. All lanes failed is a terminal
|
|
490
|
-
revise-source state, not an import state.
|
|
491
|
-
- After the lead sample/source decision is ready and approved,
|
|
492
|
-
show the next progress line:
|
|
493
|
-
`Lead source is set. I'll import the first 15-row review batch into the
|
|
494
|
-
campaign table, then ask you to Choose filters or skip. I may let the Message
|
|
495
|
-
Draft Builder prepare a template in the background, but template review waits
|
|
496
|
-
until the filter choice is resolved and the template is ready for approval.`
|
|
497
|
-
- During long post-intake work, show concise progress checkpoints before the
|
|
498
|
-
next expensive stage: source being checked, source switch/tradeoff if any,
|
|
499
|
-
lead sample usable, filter/message drafting, and message-review rule loading.
|
|
500
|
-
Each checkpoint should say what changed, what is being checked next, and why
|
|
501
|
-
that matters for the campaign. Do not invent remaining-time estimates. Example:
|
|
502
|
-
|
|
503
|
-
```text
|
|
504
|
-
This is taking a little longer than I expected, sorry. I’m being careful here
|
|
505
|
-
because the brief becomes the source of truth for the leads and messages. I’ll
|
|
506
|
-
show you the draft next so you can approve it or change it.
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
- In explicit debug/UAT runs, `Bash` is only for safe local draft-directory
|
|
510
|
-
housekeeping before the import/test batch: `mkdir`, `ls`, `find`, `test`, `pwd`, `echo`,
|
|
511
|
-
or `cat` inside the repo. In normal customer runs, do not use Bash for local
|
|
512
|
-
draft setup. Do not use
|
|
513
|
-
Bash to run interpreters/scripts (`python`, `node`, `npm`, `pnpm`, `yarn`,
|
|
514
|
-
`npx`), call APIs, query databases, inspect prompt dumps, run git, or
|
|
515
|
-
synthesize artifact content. Use `Read`/`Write`/`Edit` for artifact files and
|
|
516
|
-
MCP tools for product actions.
|
|
517
|
-
- `CampaignOffer.campaignBrief` is the stable downstream thesis source.
|
|
518
|
-
`brief.md` is an optional debug/UAT copy only; never make it the user-facing
|
|
519
|
-
approval surface in normal customer runs.
|
|
520
|
-
- The lead-source decision and lead sample must be rendered in chat and attached
|
|
521
|
-
to campaign state/search state. `lead-review.md` and `lead-sample.json` are
|
|
522
|
-
optional debug/UAT outputs of `find leads`; when they exist, describe source
|
|
523
|
-
paths as provider lanes checked (Signals, Sales Nav, Prospeo) and never
|
|
524
|
-
include custom agent names, host availability, install state, allowed-tool
|
|
525
|
-
state, or fallback implementation details.
|
|
526
|
-
- `lead-filter.md` is the primary output of `filter leads`.
|
|
527
|
-
- `rubric.json` is optional and secondary to `lead-filter.md`.
|
|
528
|
-
- `message-prep.md` is an optional speed artifact produced by the explicit
|
|
529
|
-
message path after find-leads. It can prepare proof inventory, buyer
|
|
530
|
-
objections, CTA options, gold-standard strategy maps, and candidate angles
|
|
531
|
-
from the live campaign brief, source decision, lead sample, and optional debug
|
|
532
|
-
copies.
|
|
533
|
-
- `message-candidate-drafts.md` is an optional provisional speed artifact from
|
|
534
|
-
sample rows that already look like probable good fits. It can contain rough
|
|
535
|
-
candidate messages and element tests, but it cannot select the final winner
|
|
536
|
-
and cannot override `lead-filter.md`.
|
|
537
|
-
- `message-validation.md` is the internal validation artifact produced by the
|
|
538
|
-
Message Draft Builder / `message generation` stage. It is provisional until
|
|
539
|
-
the user answers filter choice and approves the message template in chat.
|
|
540
|
-
- `message-review.md` and `message-review-decision.md` are the mandatory
|
|
541
|
-
message quality gate outputs between `message-validation.md` and
|
|
542
|
-
`approval-packet.md`.
|
|
543
|
-
- Run the dependency chain as a DAG: `create-campaign-brief` -> `find leads` ->
|
|
544
|
-
bounded import/confirm. Once the source decision, lead sample, and campaign
|
|
545
|
-
table `workflowTableId` exist, immediately start the Message Draft Builder
|
|
546
|
-
from the live campaign brief, approved source, source list, and imported
|
|
547
|
-
review-batch rows before telling the user it is in progress. The normal path
|
|
548
|
-
then reaches the `filter-choice` user gate. If the user chooses filters,
|
|
549
|
-
`post-lead-workstreams` launches filter leads and reuses the in-flight Message
|
|
550
|
-
Draft Builder work from the same basis as separate workstreams when the host
|
|
551
|
-
exposes the named Sellable post-find-leads agents or real background work.
|
|
552
|
-
First call `get_post_find_leads_scout_registry` and use the returned
|
|
553
|
-
canonical `name` values only when those names are available in the current
|
|
554
|
-
runtime. In Claude Code, use both returned Task/Agent subagents in the same
|
|
555
|
-
assistant message when the session lists them; in Codex, use both returned
|
|
556
|
-
custom scouts as disjoint subagents in the same assistant turn when the host
|
|
557
|
-
exposes them. If the names are absent, the main thread still orchestrates the
|
|
558
|
-
same filter and message branches with MCP tools/assets from the same compact
|
|
559
|
-
context. Do not surface agent install status to the customer. The existing
|
|
560
|
-
`filter-rubric` and `message-generation` steps remain focused retry and
|
|
561
|
-
resume targets.
|
|
562
|
-
- Message generation does not need `lead-filter.md` to start, but it is only
|
|
563
|
-
background template drafting until the user approves the template. The moment
|
|
564
|
-
the bounded review batch is imported, `workflowTableId` is ready, and
|
|
565
|
-
`get_rows_minimal` proves rows exist, the Message Draft Builder must start
|
|
566
|
-
from the live campaign brief, source decision, lead sample, and imported
|
|
567
|
-
campaign table sample. Do not show `Message Draft Builder: In Progress` unless
|
|
568
|
-
the worker or parent-thread fallback has actually started and runtime proof is
|
|
569
|
-
stored or returned as `watchNarration.workerDetails.messageDraftBuilder` with
|
|
570
|
-
`runId` or `fallbackId`, `statusSource`, `status`, `startedAt`, `updatedAt`,
|
|
571
|
-
`basisToken`, and the current `selectedLeadListId`/`workflowTableId`/
|
|
572
|
-
review-batch row basis. It can prepare
|
|
573
|
-
proof inventory, token strategy, and candidate angles while filter-leads
|
|
574
|
-
tightens keep/exclude rules. Template review cannot start
|
|
575
|
-
until filter choice is answered and rubrics are saved. If filters are enabled,
|
|
576
|
-
the watched browser stays on Filter Leads while the template is approved in
|
|
577
|
-
chat. After approval is saved to the campaign brief, queue the bounded
|
|
578
|
-
enrichment/filter run and prefer at least 2 usable passing rows before moving
|
|
579
|
-
to Messages. If only 1 passes, show weak-sample copy and ask whether to
|
|
580
|
-
continue, revise, import more, or skip filters.
|
|
581
|
-
If a legacy/resume host starts message prep from preview rows before import,
|
|
582
|
-
it still needs at least 3 probable good-fit rows and must reconcile the final
|
|
583
|
-
winner against the imported review batch before message review.
|
|
584
|
-
- `lead-sample.json` from `find leads` is always the message sample source.
|
|
585
|
-
`filter leads` must not create a different message sample or cause message
|
|
586
|
-
generation to fetch new prospects. The filter only marks which find-leads
|
|
587
|
-
sample rows are valid, names false-positive patterns, and provides the
|
|
588
|
-
production keep/exclude rules. Message generation may start prep or
|
|
589
|
-
provisional candidate work from probable good-fit rows in `lead-sample.json`,
|
|
590
|
-
but the final `message-validation.md` winner must cite basis rows from
|
|
591
|
-
`lead-sample.json` that still pass `lead-filter.md`.
|
|
592
|
-
- Parallel means real parallel execution, not optimistic progress copy. Source
|
|
593
|
-
scouting is sequential by default: start with the first recommended lane from
|
|
594
|
-
`flow.v2.json`, usually Signal Discovery / LinkedIn engagement. Only launch
|
|
595
|
-
multiple named source scouts when the user explicitly requested comparison, a
|
|
596
|
-
prior lane failed, or the active flow marks the first lane borderline. The
|
|
597
|
-
fallback order is plain: use Sales Nav to find ICP people who are actively
|
|
598
|
-
posting on LinkedIn; if that is not enough, search Sales Nav by titles; if
|
|
599
|
-
that is still not enough, use Prospeo for a broader account/contact path.
|
|
600
|
-
Before any source scout dispatch, call `get_source_scout_registry` and use the
|
|
601
|
-
returned canonical `name` values. The parent thread should not preload every
|
|
602
|
-
provider prompt; each scout loads only its own provider prompt. Do not write
|
|
603
|
-
"source scout agents are not installed" or similar host status into
|
|
604
|
-
customer-facing output.
|
|
605
|
-
- Source scout parallelism must not hide all provider work from the watch UI.
|
|
606
|
-
The parent thread owns the first visible provider search: call the chosen
|
|
607
|
-
provider prompt/search with the minted CampaignOffer id and provider
|
|
608
|
-
`currentStep` before waiting on source-scout results, so relevant search tabs
|
|
609
|
-
appear in real time.
|
|
610
|
-
- For post-lead workstreams, first call
|
|
611
|
-
`get_post_find_leads_scout_registry` after the review batch import confirms
|
|
612
|
-
rows. Launch the returned `message-generation` scout immediately, before the
|
|
613
|
-
filter-choice/watch copy says message work is running. When the user chooses
|
|
614
|
-
filters, launch the returned `filter-leads` scout and reuse the in-flight
|
|
615
|
-
message branch. This is the Task/Agent subagents path for the
|
|
616
|
-
`post-lead-workstreams` step. This is the same registry pattern as source
|
|
617
|
-
scouting, but the trigger is bounded review-batch import and the join gate is
|
|
618
|
-
both `lead-filter.md` and `message-validation.md` existing from the same live
|
|
619
|
-
campaign brief/source decision/imported review-batch basis. When the host can
|
|
620
|
-
launch both branches together, this is still the two Task/Agent subagents
|
|
621
|
-
path; otherwise message-generation starts first and filter-leads joins after
|
|
622
|
-
the filter choice.
|
|
623
|
-
- Runtime proof is part of the branch contract, not optional UI decoration.
|
|
624
|
-
`watchNarration.workerDetails.messageDraftBuilder.status` may be
|
|
625
|
-
`branch-running`, `fallback-active`, `spawn-failed`,
|
|
626
|
-
`fallback-superseded`, `branch-superseded`, `ready`, `blocked`,
|
|
627
|
-
`retry-needed`, or `stale`. Running copy requires `branch-running` with
|
|
628
|
-
`runId` or `fallback-active` with `fallbackId`; ready copy requires compact
|
|
629
|
-
output from the current basis. Spawn failures, stale output, or retry-needed
|
|
630
|
-
states show blocked/retry copy. Late fallback/branch outputs that are
|
|
631
|
-
superseded by a newer basis must not override the current worker status.
|
|
632
|
-
- Never run a downstream stage until the active `flow.v2.json` step's required
|
|
633
|
-
campaign state and required normal inputs exist. In normal customer runs, do
|
|
634
|
-
not create optional debug artifacts just to satisfy a file gate.
|
|
635
|
-
- Never call a tool outside the active step's `allowedTools`, and never call a
|
|
636
|
-
tool listed in the active step's `doNotAllow`.
|
|
637
|
-
- Before the source is approved, `import_leads` and `confirm_lead_list` are
|
|
638
|
-
forbidden. After source approval, import/confirm only the bounded 15-row
|
|
639
|
-
review batch. Before rubrics and the approved message set are both on the
|
|
640
|
-
campaign, the spend/send-adjacent cascade tools are forbidden: `queue_cells`,
|
|
641
|
-
`enrich_with_prospeo`, `bulk_enrich_with_prospeo`,
|
|
642
|
-
`attach_recommended_sequence`, `attach_sequence`, and `start_campaign`.
|
|
643
|
-
`create_campaign`, `update_campaign`, and `save_rubrics` are allowed only when
|
|
644
|
-
the active `flow.v2.json` step allows them.
|
|
645
|
-
- When source approval moves into import, keep chat and watch narration in the
|
|
646
|
-
same moment. If chat says import is starting, send `watchNarration` with
|
|
647
|
-
`stage: "review-batch"`, current-tense copy such as `Importing the review
|
|
648
|
-
batch`, and a no-launch safety note. Do not leave the guide saying
|
|
649
|
-
`source approved` or `I'll show the review-batch outcome` once import is
|
|
650
|
-
starting.
|
|
651
|
-
- After `import_leads` starts a provider/source import and the watched browser
|
|
652
|
-
moves to `confirm-lead-list`, the guide must describe the visible import
|
|
653
|
-
progress, not source approval. Use copy like `Scraping source leads from
|
|
654
|
-
posts` for Signal Discovery or `Importing source leads` for Sales Nav/Prospeo.
|
|
655
|
-
Do not leave `Review the source in Codex` while the Signals/Sales Nav/Prospeo
|
|
656
|
-
import progress page is visible.
|
|
657
|
-
- After the bounded review batch is present, the watched browser must move to
|
|
658
|
-
`currentStep: "filter-choice"` with `watchNarration.stage: "fit-message"` in
|
|
659
|
-
the same visible beat. Use copy like `I recommend adding filters`: say the
|
|
660
|
-
visible sample is in the campaign table, recommend adding filters when the
|
|
661
|
-
imported rows look mixed/noisy, and ask the user to choose filters or skip. If import
|
|
662
|
-
succeeds but row readback returns zero rows, do not move to filter choice; keep
|
|
663
|
-
the user in source/import recovery and ask whether to retry import, import more
|
|
664
|
-
from the approved source, or revise source. Active filtering starts only after
|
|
665
|
-
rubrics are saved; do not say filtering the batch before rubrics are saved.
|
|
666
|
-
- When the user chooses filters, immediately persist `enableICPFilters: true`
|
|
667
|
-
and `currentStep: "create-icp-rubric"` so the watched app leaves the filter
|
|
668
|
-
choice screen and shows that Codex is defining the rules in chat. After Lead
|
|
669
|
-
Fit Builder saves rubrics, move the watched browser to Filter Leads before
|
|
670
|
-
waiting for message work to finish. Persist `currentStep:
|
|
671
|
-
"apply-icp-rubric"` and `watchNarration.stage: "fit-message"`, then read the
|
|
672
|
-
bounded review batch with `get_rows_minimal`, but do not queue workflow cells
|
|
673
|
-
yet. Tell the user the fit rules are saved, the message template is being
|
|
674
|
-
finalized for approval, and enrichment/filtering will start only after that
|
|
675
|
-
approval is saved into the campaign brief. Do not call `check_rubric` in the
|
|
676
|
-
normal create-campaign-v2 path. Do not ask Use Template vs AI Generated in
|
|
677
|
-
normal runs; the Message Draft Builder template path is the default and only
|
|
678
|
-
normal path. Product Generate Message cells should not run from the background
|
|
679
|
-
template path until template/token rules are approved. After message approval,
|
|
680
|
-
update the campaign brief with an Approved Message Template containing
|
|
681
|
-
`{{...}}` tokens and keep `enableICPFilters: true`; then queue only
|
|
682
|
-
pending/error `enrichCellId` values with `queue_cells` to start enrichment and
|
|
683
|
-
filtering. Once a couple review rows pass, move to Messages so Generate
|
|
684
|
-
Message can run from the approved template. Generate Message detects template
|
|
685
|
-
mode from those tokens, not from `useMessagingTemplate`.
|
|
686
|
-
- During pre-import validation, do not call `check_rubric`; use the lead-filter
|
|
687
|
-
artifacts and only use campaign-backed scoring after Step 13 imports the
|
|
688
|
-
15-lead test batch.
|
|
689
|
-
- Resume state is based on CampaignOffer state first, then the presence and
|
|
690
|
-
completeness of the chained debug artifacts. Never treat file presence as the
|
|
691
|
-
durable source of truth after the campaign exists.
|
|
692
|
-
- Preserve the Phase 83 thesis. Do not rewrite product, ICP, offer, or message
|
|
693
|
-
hypothesis sections during preview validation.
|
|
694
|
-
- Exception: brief-validated may rewrite §3 Campaign Thesis AND §12 Next Steps
|
|
695
|
-
when Phase-84 lead-yield data clearly contradicts a Phase-83 UNVALIDATED
|
|
696
|
-
decision on primary lead-source. "Clearly contradicts" = the Phase-83
|
|
697
|
-
primary source yields 0 FIT while an alternative source yields ≥ 3 FIT in
|
|
698
|
-
the same 15-row test sample (or an equivalent ≥ 5× ratio at larger samples).
|
|
699
|
-
Every rewrite MUST cite specific yield numbers from `lead-review.md`. All
|
|
700
|
-
other Phase-83 brief sections remain read-only. See
|
|
701
|
-
`references/filter-leads.md` § Brief-Validated Rewrite Authority for the
|
|
702
|
-
full evidence shape.
|
|
703
|
-
- Every artifact write uses `tmp + rename` so a failed write leaves the prior
|
|
704
|
-
artifact intact.
|
|
705
|
-
- If a required upstream artifact is missing, stop and route back to the
|
|
706
|
-
missing step instead of guessing.
|
|
707
|
-
- Before importing the 15-lead test batch, persist a customer-facing
|
|
708
|
-
`message-review.md` and `message-review-decision.md` so the message decision
|
|
709
|
-
can be inspected later.
|
|
710
|
-
- The message review must show one concrete sample message rendered as the
|
|
711
|
-
recipient would see it, in addition to the approved message template. Do not
|
|
712
|
-
make the user mentally expand `{{tokens}}`.
|
|
713
|
-
- Do not include sequence, cadence, sending-window, mailbox, or campaign
|
|
714
|
-
settings review in `message-review.md`. Those come after the 15-lead test
|
|
715
|
-
batch, in the settings/sequence handoff.
|
|
716
|
-
- Do not include post-accept DMs, connection-accepted follow-ups, day-2 / day-7
|
|
717
|
-
follow-ups, second touches, reply branches, or any other sequence-shaped copy
|
|
718
|
-
in `message-review.md`. If
|
|
719
|
-
`message-validation.md` contains those, mark the message review as
|
|
720
|
-
`revise-messaging` and route back to message generation even if the artifact
|
|
721
|
-
says `Status: confirmed`.
|
|
722
|
-
- Persist `customer-roleplay.md` when a customer/operator roleplay critique is
|
|
723
|
-
run. This critique can recommend a decision, but it can never replace
|
|
724
|
-
`approve-message` for lead import, workflow-table processing, sequence attach,
|
|
725
|
-
or start.
|
|
726
|
-
|
|
727
|
-
</rules>
|
|
728
|
-
|
|
729
|
-
<conditional_gates>
|
|
730
|
-
|
|
731
|
-
There are six customer-visible gates in the net-new hosted flow:
|
|
19
|
+
If the tail begins, load the tail prompt before any auto-execute or
|
|
20
|
+
validate-sample tool:
|
|
732
21
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
- `lead-review` / source decision asks whether to approve the selected source
|
|
737
|
-
path and sample before moving into filter/message work. Do not skip this by
|
|
738
|
-
compressing the source decision into message review.
|
|
739
|
-
- `filter-choice` asks whether to use filters or skip after the non-empty
|
|
740
|
-
review batch is imported. This is the first post-import user gate.
|
|
741
|
-
- `message-review` is the mandatory template quality gate. It asks only whether
|
|
742
|
-
to proceed with the selected
|
|
743
|
-
message (`approve-message`) or run one more messaging revision
|
|
744
|
-
(`revise-messaging`). `approve-message` authorizes syncing the approved
|
|
745
|
-
template/token rules into the campaign brief and queueing/observing the
|
|
746
|
-
review-batch cascade.
|
|
747
|
-
- The sender/settings/sequence handoff is the launch gate. After message
|
|
748
|
-
validation, use Settings to help the user connect or select a LinkedIn sender.
|
|
749
|
-
Explain Slack reply review before launch. After sender selection, attach the
|
|
750
|
-
recommended sequence and move the watched UI to Send. Starting the campaign
|
|
751
|
-
still waits until the user explicitly greenlights start.
|
|
752
|
-
|
|
753
|
-
Auto-continue without a structured question gate when the artifact says
|
|
754
|
-
`Status: confirmed` (or equivalent), confidence is high/medium, volume is
|
|
755
|
-
viable, and there is no strategic tradeoff.
|
|
756
|
-
|
|
757
|
-
Ask the user only when one of these is true:
|
|
758
|
-
|
|
759
|
-
- `Status` is rejected, unclear, revise-find-leads, revise-filter, or
|
|
760
|
-
confirm-with-user.
|
|
761
|
-
- Projected usable leads are below the campaign floor for the market, or the
|
|
762
|
-
sample pass rate suggests heavy filtering will make the campaign miss.
|
|
763
|
-
- The source path contradicts the brief, removes the buyer segment that made
|
|
764
|
-
the campaign compelling, or proves the provider is matching titles but not
|
|
765
|
-
actual buyers.
|
|
766
|
-
- Filter rules are not production-rubric-translatable from row data, enrichment,
|
|
767
|
-
or normal public research.
|
|
768
|
-
- Message validation has a blocking skeptical-prospect issue, no selected
|
|
769
|
-
winner, weak token plan, or a recommendation to revise. Even when it is
|
|
770
|
-
confirmed, render the `message-review` gate before importing the test batch so
|
|
771
|
-
the founder can approve or revise the message deliberately.
|
|
772
|
-
|
|
773
|
-
When asking subjective strategy questions (buyer scope, first ask, proof
|
|
774
|
-
emphasis, tone, lead-source preference), always make it clear the user can give
|
|
775
|
-
a custom answer. Add an explicit `Other / custom` option to each subjective
|
|
776
|
-
question. Do not rely on prose like "you can add detail" as the only custom
|
|
777
|
-
path.
|
|
778
|
-
Every subjective setup question is single-choice in both Claude Code and
|
|
779
|
-
Codex. Use mutually exclusive options, set or assume `multiSelect: false`, and
|
|
780
|
-
never use checkbox or multi-select wording that invites selecting several
|
|
781
|
-
options. If a blended answer is likely, make the blend a single named option or
|
|
782
|
-
route it through `Other / custom` and a normal-chat follow-up.
|
|
783
|
-
Do not batch setup as a Claude Code multi-select wizard; buyer, offer/CTA,
|
|
784
|
-
proof, and lead source remain single-choice questions even when the host
|
|
785
|
-
displays them in a sequence.
|
|
786
|
-
Use customer-facing question wording:
|
|
787
|
-
|
|
788
|
-
- target prospects: `Who should be the target prospects for this campaign?`
|
|
789
|
-
- main CTA / offer: `What should the main CTA or offer be?`
|
|
790
|
-
- proof emphasis: `Which proof point would most increase this buyer's confidence in {{company}}?`
|
|
791
|
-
- lead source: `How should we get the people for this campaign?`
|
|
792
|
-
|
|
793
|
-
Do not offer quantified reply-rate, meeting-rate, pipeline, revenue, or ROI
|
|
794
|
-
claims as setup proof options unless the user supplied verified benchmark data
|
|
795
|
-
for this exact workspace/sender. If such claims appear in research, label them
|
|
796
|
-
as unavailable/unsupported and use founder/operator credibility, product
|
|
797
|
-
capability, or verified customer proof instead.
|
|
798
|
-
This is a hard guardrail for both option labels and option descriptions: never
|
|
799
|
-
write setup proof option text with numeric outcome language such as `25% reply`,
|
|
800
|
-
`25%-reply`, `reply-rate`, `meeting-rate`, `pipeline`, `revenue`, or `ROI`
|
|
801
|
-
unless that exact benchmark is verified for this workspace/sender. If a profile
|
|
802
|
-
or case study contains that language, strip the number and convert the option to
|
|
803
|
-
non-quantified founder/operator credibility or product capability.
|
|
804
|
-
|
|
805
|
-
Ask the lead-source question as the last question in the first strategy
|
|
806
|
-
batch, after buyer, offer/ask, and proof/safety are understood. Frame supplied
|
|
807
|
-
lists as optional, not required. The three visible options are exactly:
|
|
808
|
-
|
|
809
|
-
1. `Find people for me (recommended if you don't already have your own list)`
|
|
810
|
-
2. `I have a CSV of profiles to reach out to`
|
|
811
|
-
3. `I have a CSV of companies/domains I want to target`
|
|
812
|
-
|
|
813
|
-
Do not expose provider or implementation paths as the user's lead-source
|
|
814
|
-
choices. Never label the structured options as `engagers`, `titles`,
|
|
815
|
-
`Signals`, `Sales Nav`, `Prospeo`, `search LinkedIn posts`, or similar. Those
|
|
816
|
-
are internal scouting methods for the `Find people for me` path, not choices a
|
|
817
|
-
first-time user should have to understand.
|
|
818
|
-
|
|
819
|
-
Keep `Other / custom` available for freeform answers such as a pasted list,
|
|
820
|
-
an existing Sellable lead list, or another source idea. Do not put existing
|
|
821
|
-
Sellable lead lists in the main three-option first batch; support them through
|
|
822
|
-
custom/freeform input. If the user chooses the company/domain option, ask in
|
|
823
|
-
normal chat whether they have a CSV, pasted domains, or pasted company names.
|
|
824
|
-
If the user pastes up to 100 LinkedIn profile URLs or company domains,
|
|
825
|
-
normalize the paste into a temporary local CSV and continue through the
|
|
826
|
-
matching CSV preview path. Mixed, ambiguous, malformed, or oversized pastes
|
|
827
|
-
should ask for a real CSV file instead of guessing. Uploaded CSV support is
|
|
828
|
-
larger than paste support: LinkedIn profile CSVs can contain up to 7,500 rows;
|
|
829
|
-
domain CSVs can contain up to 7,500 rows but only 1,000 unique domains.
|
|
830
|
-
|
|
831
|
-
Avoid internal wording like `Which proof points should the message be allowed
|
|
832
|
-
to lean on?` because it describes the artifact, not the founder decision.
|
|
833
|
-
|
|
834
|
-
When auto-continuing, show one concise progress line and immediately continue.
|
|
835
|
-
Do not create a review question whose only useful answer is "looks good".
|
|
836
|
-
|
|
837
|
-
</conditional_gates>
|
|
838
|
-
|
|
839
|
-
<step_contracts>
|
|
840
|
-
|
|
841
|
-
## Step 1: Find Leads
|
|
842
|
-
|
|
843
|
-
Use the shell-first CampaignOffer campaignId for lead-source preview.
|
|
844
|
-
Campaignless preview mode is only allowed before the campaign shell is minted;
|
|
845
|
-
it is legacy-only and not part of the active flow once a CampaignOffer exists.
|
|
846
|
-
|
|
847
|
-
Write:
|
|
848
|
-
|
|
849
|
-
- `lead-review.md`
|
|
850
|
-
- `lead-sample.json`
|
|
851
|
-
- optional `lead-source-intake.json` when the user intentionally supplied a
|
|
852
|
-
source
|
|
853
|
-
|
|
854
|
-
Required behavior:
|
|
855
|
-
|
|
856
|
-
- pass the CampaignOffer campaignId as `campaignOfferId` to every provider
|
|
857
|
-
prompt/search that can persist into campaign state:
|
|
858
|
-
`get_provider_prompt({ provider, campaignOfferId, confirmed: true })`,
|
|
859
|
-
`search_signals`, `search_sales_nav`, and `search_prospeo`. This lets the user
|
|
860
|
-
watch source work in the campaign during intake.
|
|
861
|
-
- provider prompt preflight and interaction-mode approval are in-memory. On
|
|
862
|
-
resume or MCP restart, call `get_provider_prompt({ provider, campaignOfferId })`
|
|
863
|
-
again before any provider search/import; do not assume CampaignOffer state
|
|
864
|
-
proves preflight happened in this process. Immediately before `import_leads`,
|
|
865
|
-
reload the provider prompt in the same turn with
|
|
866
|
-
`get_provider_prompt({ provider, campaignOfferId })`, even when source preview
|
|
867
|
-
loaded it in a previous turn.
|
|
868
|
-
- if CampaignOffer campaignId is missing, stop and recover shell creation before
|
|
869
|
-
sourcing; do not run a campaignless source path in the active flow.
|
|
870
|
-
- do not import leads
|
|
871
|
-
- do not import into the campaign table, queue cells, attach a sequence, or start
|
|
872
|
-
the campaign
|
|
873
|
-
- do not create lead-list rows except explicit user-supplied preview flows
|
|
874
|
-
allowed by `flow.v2.json`
|
|
875
|
-
- only mutate campaign-attached source preview state in the narrow watch-mode
|
|
876
|
-
ways allowed by the active flow step
|
|
877
|
-
- use the default sequential source viability funnel when the user did not
|
|
878
|
-
specify a source. The goal is to choose a source quickly enough to keep the
|
|
879
|
-
watched campaign moving, not to compare every plausible lane in parallel.
|
|
880
|
-
Run only enough evidence for the current lane to pass or fail the quick gate,
|
|
881
|
-
then stop on the first viable source unless the user asked to compare.
|
|
882
|
-
User-facing fallback copy should stay fifth-grade clear: people engaging with
|
|
883
|
-
relevant LinkedIn posts -> Sales Nav to find ICP people actively posting on
|
|
884
|
-
LinkedIn -> search by titles -> Prospeo for a broader account/contact path.
|
|
885
|
-
The older provider label `broader Sales Nav` maps to the plain-language
|
|
886
|
-
`search by titles` fallback; `Prospeo only as the fallback` maps to the
|
|
887
|
-
plain-language broader account/contact path. Keep user-facing copy simple.
|
|
888
|
-
1. Start with LinkedIn Engagement / active LinkedIn posts (internal provider:
|
|
889
|
-
Signals / `signal-discovery`) because recent engagement gives the strongest
|
|
890
|
-
message context and expected reply-rate upside. Search intersection keyword
|
|
891
|
-
lanes that combine the campaign anchor with the buyer pain/use case/ICP
|
|
892
|
-
role, review finalist posts, promote a narrow sample set with
|
|
893
|
-
`select_promising_posts` before fetching engagers when a campaign shell
|
|
894
|
-
exists, fetch top-post engagers, estimate ICP-fit rate, compute posts
|
|
895
|
-
needed for the target good-fit lead count, and only then recommend the
|
|
896
|
-
selected post set or move to the next source.
|
|
897
|
-
2. If Signals does not have enough recent, relevant, ICP-looking engagers,
|
|
898
|
-
switch to Sales Nav with recent activity when the target can be expressed
|
|
899
|
-
as title/persona/company filters. Run preview filters, inspect preview rows,
|
|
900
|
-
validate the filters applied, and estimate scalable-fit volume. If the
|
|
901
|
-
preview/projected usable pool is below the target good-fit count, loosen
|
|
902
|
-
nonessential filters before presenting Sales Nav as the scale fallback.
|
|
903
|
-
3. If recent-activity Sales Nav is too small or noisy, broaden to normal Sales
|
|
904
|
-
Nav title + company filters and call out the weaker activity context.
|
|
905
|
-
4. Use Prospeo Contact only when the campaign has a domain/account path, the
|
|
906
|
-
user supplied domains, the user asked for hiring/growth/account triggers,
|
|
907
|
-
or the LinkedIn-first paths fail. Estimate email/contact scale and call out
|
|
908
|
-
weaker LinkedIn activity.
|
|
909
|
-
- source-specific user direction overrides the default funnel. If the user
|
|
910
|
-
names hiring signals, account/domain lists, company growth triggers, or target
|
|
911
|
-
accounts, start with Prospeo. If they supply profiles or a CSV, start with the
|
|
912
|
-
supplied-list preview. If they name posts, comments, creators, or engagement,
|
|
913
|
-
start with Signal Discovery. If they name titles/personas/company filters,
|
|
914
|
-
start with Sales Nav. If they explicitly ask for a comparison, compare only
|
|
915
|
-
those requested sources.
|
|
916
|
-
- failed or empty source lanes do not import leads. A timeout/error, zero raw
|
|
917
|
-
results, weak ICP fit, or weak message context must trigger the next approved
|
|
918
|
-
lane or a revision question before import. All lanes failed is a terminal
|
|
919
|
-
revise-source state, not an import state.
|
|
920
|
-
- run source scouts in parallel only when the user explicitly requested a
|
|
921
|
-
comparison, the current turn is resuming from already-started parallel scouts,
|
|
922
|
-
or the first viable source is borderline and one cheap fallback check is
|
|
923
|
-
necessary for the recommendation. Call `get_source_scout_registry` first so
|
|
924
|
-
new scouts can be added without prompt rewrites. In Codex, explicitly spawn
|
|
925
|
-
named custom subagents in the same turn when the host exposes them:
|
|
926
|
-
`source-scout-linkedin-engagement` / LinkedIn Engagement Scout,
|
|
927
|
-
`source-scout-sales-nav`, and `source-scout-prospeo-contact` for the requested
|
|
928
|
-
or fallback lanes. Codex does not infer this from generic "compare paths"
|
|
929
|
-
wording. In Claude Code, launch the matching Task/Agent subagents only when
|
|
930
|
-
the current session lists those names. If they are absent, run the same
|
|
931
|
-
provider probes with MCP tools from the parent thread and keep
|
|
932
|
-
`lead-review.md` focused on source evidence, not host-agent availability.
|
|
933
|
-
- after every Sales Nav preview, validate that filters actually applied before
|
|
934
|
-
using the lane in `lead-review.md`: `searchUrl` should include filters, the
|
|
935
|
-
first page should match the intended roles/companies, and the result count
|
|
936
|
-
should be plausible. If Sales Nav returns a giant unfiltered pool, drops the
|
|
937
|
-
filters, or errors after one clean retry, call it out as a provider/tool
|
|
938
|
-
issue and do not recommend Sales Nav.
|
|
939
|
-
- when the brief or user names target roles, Sales Nav must preserve those role
|
|
940
|
-
names through `CURRENT_TITLE` lookups. Do not use broad seniority as a
|
|
941
|
-
substitute for role intent. VP Sales, VP Revenue, CRO, Head of Growth, and
|
|
942
|
-
similar targets should stay visible in the filter recipe and the source
|
|
943
|
-
explanation.
|
|
944
|
-
- for Signals-first campaigns, raw post search volume is only inventory, not
|
|
945
|
-
lead volume. `492 post results` means matching LinkedIn posts found across
|
|
946
|
-
keyword lanes; it does not mean 492 prospects. The source decision must name
|
|
947
|
-
the actual posts we would use, show why they won, and estimate usable engagers
|
|
948
|
-
from those posts after headline/sample filtering
|
|
949
|
-
- for Signals-first campaigns, keyword lanes must be intersection-first. If the
|
|
950
|
-
campaign anchor is `Claude`, `MCP`, `AI agents`, or another broad technology,
|
|
951
|
-
do not make broad anchor-only lanes the main test. Combine the anchor with the
|
|
952
|
-
specific wedge and buyer pain, such as outbound, GTM automation, LinkedIn
|
|
953
|
-
outreach, AI SDR skepticism, founder-led sales, RevOps, or the ICP role. Treat
|
|
954
|
-
broad anchor-only lanes as fallback inventory only, and retarget before
|
|
955
|
-
sampling if the first pass is broad.
|
|
956
|
-
- Signals viability is based on estimated ICP-fit reachable engagers, not raw
|
|
957
|
-
post count and not whether it beats Sales Nav scale. Keep source-capacity
|
|
958
|
-
planning separate from the 15-row review-batch import: the default source
|
|
959
|
-
target is 300 likely good-fit leads, while `import.importLimit` remains 15 for
|
|
960
|
-
the first campaign review batch. If 5-8 selected posts can plausibly produce
|
|
961
|
-
~150+ ICP-fit warm prospects before final filtering, keep Signals as a viable
|
|
962
|
-
focused option, but say it is below the default 300-lead source target unless
|
|
963
|
-
the math shows otherwise.
|
|
964
|
-
- When Signals is viable-but-smaller and Sales Nav or Prospeo is more scalable,
|
|
965
|
-
the user-facing lead review must present the choice: Signals for a warmer,
|
|
966
|
-
smaller, higher-reply-upside first batch versus Sales Nav/Prospeo for broader
|
|
967
|
-
scale. Recommend the source you believe should win, often Sales Nav when scale
|
|
968
|
-
matters, but keep the smaller Signals lane available as a real option.
|
|
969
|
-
- user-facing source logic must use sample-backed numbers, not vibes. Show the
|
|
970
|
-
numerator, denominator, sample basis, and an easy percentage or range, e.g.
|
|
971
|
-
`18 of 40 sampled engagers fit the ICP (~45%, directional)`. If the sample is
|
|
972
|
-
small, say it is directional. If an estimate depends on assumptions, show the
|
|
973
|
-
math plainly: `8 eligible posts x ~140 reachable engagers/post x ~35-45% ICP
|
|
974
|
-
fit x cleanup factor = ~300-500 likely usable warm leads`.
|
|
975
|
-
- source progress updates should expose the confidence-building numbers as soon
|
|
976
|
-
as they exist: keyword lanes searched, timeframe used, post results by lane,
|
|
977
|
-
finalist posts reviewed, engagers fetched, sampled engagers, sampled fits,
|
|
978
|
-
estimated usable leads, and what is still unknown. Do not wait until the final
|
|
979
|
-
lead-source review to show those numbers.
|
|
980
|
-
- Signals source decisions should prefer fresh posts. Default to posts from the
|
|
981
|
-
last 30 days, prefer the last 7-14 days when quality is comparable, and call
|
|
982
|
-
out any older post as a deliberate tradeoff. Do not hide post age inside the
|
|
983
|
-
raw search count
|
|
984
|
-
- default source quality target is 300 likely good-fit leads for scalable
|
|
985
|
-
outbound unless the campaign or user supplies a different source target.
|
|
986
|
-
Compute required engagers from the observed fit rate: `target good-fit leads /
|
|
987
|
-
sampled fit rate`. For example, 20 good fits per 100 engagers means a 300
|
|
988
|
-
good-fit source target needs about 1,500 engagers scraped; use average
|
|
989
|
-
reachable engagers per right-content post to calculate how many posts are
|
|
990
|
-
needed. Accept
|
|
991
|
-
~150+ likely ICP-fit warm prospects as viable for a focused Signals-first
|
|
992
|
-
campaign or first review batch only when the user is choosing warmth over
|
|
993
|
-
scale. Name the volume tradeoff in `lead-review.md` and the source approval
|
|
994
|
-
card rather than forcing a discard.
|
|
995
|
-
- if `lead-source-intake.json` is present, read `sourceType`,
|
|
996
|
-
`sourceInputMode`, file path or existing lead-list ID, selected columns,
|
|
997
|
-
confirmation token, normalized counts, and any preview-created
|
|
998
|
-
`domainFilterId`
|
|
999
|
-
- supplied LinkedIn profile CSVs call `load_csv_linkedin_leads` in preview mode
|
|
1000
|
-
only before rubrics and the approved message set are ready; do not pass
|
|
1001
|
-
provider-import params during the preview. Use `campaignOfferId` only to
|
|
1002
|
-
attach the preview/source choice to the campaign UI. In Step 13, this branch
|
|
1003
|
-
is a two-stage batch path:
|
|
1004
|
-
materialize the full supplied CSV into a Sellable lead-list table first, then
|
|
1005
|
-
use the returned `leadListId` as `sourceLeadListId` for the bounded campaign
|
|
1006
|
-
review import
|
|
1007
|
-
- supplied company/domain CSVs call `load_csv_domains`; confirmation is allowed
|
|
1008
|
-
to produce a `domainFilterId` for Prospeo sampling. Run the preview search
|
|
1009
|
-
with `campaignOfferId`. In Step 13, use the same `domainFilterId` in a
|
|
1010
|
-
campaign-associated Prospeo people search, then import.
|
|
1011
|
-
- existing Sellable lead lists skip provider discovery and sample from the
|
|
1012
|
-
existing rows; do not clone/import the list until rubrics are saved and the
|
|
1013
|
-
approved message set is in the campaign brief
|
|
1014
|
-
- do not call `save_domain_filters` in the pre-approval create-campaign path
|
|
1015
|
-
|
|
1016
|
-
`lead-review.md` must state:
|
|
1017
|
-
|
|
1018
|
-
- validation status: `confirmed`, `rejected`, or `unclear`
|
|
1019
|
-
- confidence
|
|
1020
|
-
- provider path used
|
|
1021
|
-
- search lanes tested, with keyword/filter names and the timeframe used
|
|
1022
|
-
- post/result counts by lane for discovery sources
|
|
1023
|
-
- supplied source type when applicable (`normal-discovery`,
|
|
1024
|
-
`supplied-linkedin-profiles`, `supplied-domains`, or `existing-lead-list`)
|
|
1025
|
-
- row/domain counts, invalid counts, duplicate counts, and sample method for
|
|
1026
|
-
supplied sources
|
|
1027
|
-
- preview count
|
|
1028
|
-
- ICP match rate with numerator/denominator, sample basis, and a simple
|
|
1029
|
-
percentage/range; never percent-only
|
|
1030
|
-
- volume comparison
|
|
1031
|
-
- source viability: expected source volume, expected usable leads after
|
|
1032
|
-
filtering, source activity/warmth indicators, cleanup risk, and confidence
|
|
1033
|
-
basis
|
|
1034
|
-
- do not forecast connection acceptance, reply rate, meetings, pipeline,
|
|
1035
|
-
revenue, or ROI unless the user supplied verified benchmark data for this
|
|
1036
|
-
exact workspace/sender. If no verified benchmark exists, state that
|
|
1037
|
-
performance is not estimated from this source review.
|
|
1038
|
-
- for Signals-first paths: top candidate posts reviewed, selected post URLs,
|
|
1039
|
-
post author, post topic/excerpt, post age or posted date, engagement count,
|
|
1040
|
-
sampled engager count per selected post, sampled fit count per selected post,
|
|
1041
|
-
estimated usable engagers per selected post, and why each selected post is
|
|
1042
|
-
better than discarded posts
|
|
1043
|
-
- for Signals-first paths: total raw post results by lane, number of finalist
|
|
1044
|
-
posts reviewed, number of selected posts, total engagers fetched, deduped
|
|
1045
|
-
sampled people count, sampled fit count, and the estimated likely usable people
|
|
1046
|
-
range. Explicitly distinguish `posts found`, `engagers sampled`, and `usable
|
|
1047
|
-
people estimated`.
|
|
1048
|
-
- source decision: best path, why it won, pros, cons/tradeoffs, and discarded
|
|
1049
|
-
source paths with the reason each lost
|
|
1050
|
-
- repeated false-positive patterns
|
|
1051
|
-
- message handoff: 2-5 sample rows that look like strong/probable good fits,
|
|
1052
|
-
with row identifiers and the reason each is safe enough for message thinking
|
|
1053
|
-
- suggested next action or revision
|
|
1054
|
-
|
|
1055
|
-
For normal LinkedIn discovery, `lead-review.md` must include these
|
|
1056
|
-
customer-visible sections with literal headings:
|
|
1057
|
-
|
|
1058
|
-
- `## Source Decision`
|
|
1059
|
-
- `## Evidence Snapshot`
|
|
1060
|
-
- `## Selected Signal Posts` for Signals-first campaigns
|
|
1061
|
-
- `## Source Viability`
|
|
1062
|
-
- `## Sample Leads` for Signals-first campaigns
|
|
1063
|
-
- `## Pros`
|
|
1064
|
-
- `## Tradeoffs`
|
|
1065
|
-
- `## Discarded Paths`
|
|
1066
|
-
|
|
1067
|
-
For Signals-first campaigns, `## Selected Signal Posts` must include a compact
|
|
1068
|
-
table with one row per selected or finalist post:
|
|
1069
|
-
|
|
1070
|
-
- post URL
|
|
1071
|
-
- post author
|
|
1072
|
-
- posted date or recency
|
|
1073
|
-
- topic/excerpt
|
|
1074
|
-
- total engagement or estimated engagers
|
|
1075
|
-
- sampled engagers
|
|
1076
|
-
- sampled fits
|
|
1077
|
-
- estimated usable leads
|
|
1078
|
-
- why use / why discard
|
|
1079
|
-
|
|
1080
|
-
`## Evidence Snapshot` must include a compact numbers-first table:
|
|
1081
|
-
|
|
1082
|
-
- source lane / keyword or filter
|
|
1083
|
-
- timeframe searched
|
|
1084
|
-
- raw results found
|
|
1085
|
-
- finalist posts or preview rows reviewed
|
|
1086
|
-
- sampled people
|
|
1087
|
-
- sampled fits, shown as `n/N` plus a simple percentage/range
|
|
1088
|
-
- estimated usable people
|
|
1089
|
-
- confidence note (`sample-backed`, `directional`, or `needs more sample`)
|
|
1090
|
-
|
|
1091
|
-
For Signals-first campaigns, `## Sample Leads` must group representative sample
|
|
1092
|
-
rows by source post when possible, so the user can see not just that the search
|
|
1093
|
-
found posts, but which posts produce believable prospects.
|
|
1094
|
-
|
|
1095
|
-
`## Source Viability` must include expected source volume, expected usable
|
|
1096
|
-
leads after filtering, source activity/warmth indicators, cleanup risk, and
|
|
1097
|
-
estimate basis. Do not include likely connection acceptance or reply-rate
|
|
1098
|
-
ranges unless verified benchmark data was supplied by the user for this exact
|
|
1099
|
-
workspace/sender.
|
|
1100
|
-
|
|
1101
|
-
When showing `lead-review.md` to the user, render a slim decision summary in
|
|
1102
|
-
chat, not the full evidence table. Use rendered Markdown directly with short
|
|
1103
|
-
indexed sections and bullet lines; do not use fenced code blocks for the
|
|
1104
|
-
user-facing lead review. The visible response must be a compact math-first card,
|
|
1105
|
-
not a research memo. It must include only:
|
|
1106
|
-
|
|
1107
|
-
- `Lead source decision`
|
|
1108
|
-
- `Source recommendation: {source}` with the concrete recipe. For Sales Nav,
|
|
1109
|
-
name the actual role/title, company-size, geography, industry/account, and
|
|
1110
|
-
activity filters. For Signals, name the selected post set. For Prospeo, name
|
|
1111
|
-
the account/domain and title recipe.
|
|
1112
|
-
- `Math:` with these labels and values:
|
|
1113
|
-
`Eligible posts`, `Sample`, `ICP-fit`, `Good-fit / 100 engagers`,
|
|
1114
|
-
`Required engagers`, `Avg engagers/post`, `Good-fit / post`, `Source target`,
|
|
1115
|
-
`Posts needed`, `Selected`, `Review batch`, `Expected good-fit leads`, and
|
|
1116
|
-
`Scale option`.
|
|
1117
|
-
- `Why this source:` with at most two bullets.
|
|
1118
|
-
- `Watch link: {watchUrl}` only when the campaign shell exists and the host
|
|
1119
|
-
needs a handoff link.
|
|
1120
|
-
- the concrete source approval question and options.
|
|
1121
|
-
|
|
1122
|
-
Do not include keyword-lane tables, LinkedIn-post-sampled tables, sample-lead
|
|
1123
|
-
lists, or long tradeoff prose in the default approval packet. Keep those details
|
|
1124
|
-
in `lead-review.md` or campaign/source decision state. The math block is the
|
|
1125
|
-
bottom-line arithmetic that makes the recommendation obvious. For example:
|
|
1126
|
-
`Eligible posts: 12 outbound + Claude posts. Sample: 25/125 ICP fits. ICP-fit:
|
|
1127
|
-
~20%, directional. Good-fit / 100 engagers: ~20 before cleanup. Required
|
|
1128
|
-
engagers: ~1,500 to reach 300 good-fit prospects. Avg engagers/post: ~300
|
|
1129
|
-
reachable. Good-fit / post: ~60. Source target: 300 good-fit leads. Posts
|
|
1130
|
-
needed: about 5 right-content posts. Selected: 5 posts. Review batch: import
|
|
1131
|
-
only 15 campaign rows first. Expected good-fit leads: ~300 before stricter
|
|
1132
|
-
filtering. Scale option: Sales Nav can broaden to founder/GTM/RevOps filters if
|
|
1133
|
-
you want colder scale, but loses the engaged-with-this-content message hook.` If
|
|
1134
|
-
the selected posts only support the 15-row review batch or a smaller warm pilot,
|
|
1135
|
-
say that plainly and do not imply the lane can hit the source target. For
|
|
1136
|
-
Sales Nav/Prospeo
|
|
1137
|
-
alternatives, include preview/raw volume, sampled usable rows as `n/N` plus
|
|
1138
|
-
percentage/range, estimated usable range, and the warmth or context tradeoff.
|
|
1139
|
-
If Sales Nav preview volume is too tight, broaden nonessential filters before
|
|
1140
|
-
using it as the scale option, or label it constrained and name the next fallback.
|
|
1141
|
-
Do not use percent-only fit rates or unsupported reply-rate claims.
|
|
1142
|
-
|
|
1143
|
-
The first sentence of the visible decision must make the actual choice clear:
|
|
1144
|
-
`I recommend {primary source} using {exact filter/source recipe}. The runner-up
|
|
1145
|
-
is {source} because {reason}.` Do not make the user infer the decision from
|
|
1146
|
-
numbers alone.
|
|
1147
|
-
|
|
1148
|
-
Before asking for lead-source approval, make the watched campaign show the
|
|
1149
|
-
recommended primary source lane. Call
|
|
1150
|
-
`update_campaign({ campaignId, leadSourceType: "new", leadSourceProvider,
|
|
1151
|
-
currentStep, watchNarration })` with `currentStep` set to the provider lane
|
|
1152
|
-
being recommended (`sales-nav`, `signal-discovery`, or `prospeo`). If the last
|
|
1153
|
-
sampled lane was Signals but the recommendation is Sales Nav, switch the
|
|
1154
|
-
watched provider page to Sales Nav before asking the question so the user can
|
|
1155
|
-
see what they are approving and why. No leads import until the user approves.
|
|
22
|
+
```text
|
|
23
|
+
get_subskill_prompt({ subskillName: "create-campaign-v2-tail" })
|
|
24
|
+
```
|
|
1156
25
|
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
`
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
26
|
+
CampaignOffer state and the watch link are canonical. Resume, gating, and
|
|
27
|
+
handoff read campaign state first: `campaignId`, `watchUrl`, `campaignBrief`,
|
|
28
|
+
`currentStep`, source/search association, `selectedLeadListId`,
|
|
29
|
+
`workflowTableId`, `leadScoringRubrics`, `approvedMessageTemplate`,
|
|
30
|
+
`senderIds`, `sequenceTemplate`, and running state. Local draft files are
|
|
31
|
+
legacy debug/UAT diagnostics only. In normal customer runs, do not create,
|
|
32
|
+
read, link, or surface local draft artifacts unless the user explicitly asks
|
|
33
|
+
for debug output.
|
|
34
|
+
|
|
35
|
+
## Normal Flow
|
|
36
|
+
|
|
37
|
+
1. Bootstrap and tell the user the active Sellable workspace.
|
|
38
|
+
2. Resolve campaign identity before strategy questions.
|
|
39
|
+
3. Research the client/company enough to draft a concrete brief.
|
|
40
|
+
4. Create the watchable campaign shell with `create_campaign` and the v1 brief.
|
|
41
|
+
5. Surface the direct watch link.
|
|
42
|
+
6. Choose and approve the lead source.
|
|
43
|
+
7. Import and confirm only the bounded first review batch.
|
|
44
|
+
8. Ask whether to use filters or skip them.
|
|
45
|
+
9. Persist lead rubrics when filters are enabled.
|
|
46
|
+
10. Generate a first-message template recommendation from the imported review
|
|
47
|
+
rows.
|
|
48
|
+
11. Review and approve/revise the message.
|
|
49
|
+
12. Sync the approved template into the campaign brief.
|
|
50
|
+
13. Validate the bounded review batch, then move to Settings, sender, sequence,
|
|
51
|
+
and explicit launch greenlight.
|
|
52
|
+
|
|
53
|
+
There is no normal approval-packet, commit-gate, atomic-mint, or local
|
|
54
|
+
artifact-validation step. Those belong only to legacy validation/rehearsal
|
|
55
|
+
flows and the separate `create-campaign-v2-validation` subskill.
|
|
56
|
+
|
|
57
|
+
## Identity-First Campaign Setup
|
|
58
|
+
|
|
59
|
+
Do not treat the active Sellable workspace as the campaign subject. Resolve the
|
|
60
|
+
client/company first, then draft the buyer, offer, proof, and source plan.
|
|
61
|
+
|
|
62
|
+
First visible request when no identity is known:
|
|
1169
63
|
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
must be concrete, such as `Approve Sales Nav filters`, `Use warmer Signals
|
|
1174
|
-
posts`, `Try Prospeo/account search`, and `Revise source`.
|
|
1175
|
-
Immediately above that approval question, render the `Source math before
|
|
1176
|
-
approval` block. Do not ask the user to approve from the recommendation alone;
|
|
1177
|
-
show the math tying relevant posts, available engagers, sampled fit, expected
|
|
1178
|
-
usable lead count, posts needed for the target, and the scale alternative
|
|
1179
|
-
together first.
|
|
64
|
+
```text
|
|
65
|
+
First, paste the LinkedIn profile or company website for the client/company this campaign is for.
|
|
66
|
+
```
|
|
1180
67
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
each post can produce. If no engagers could be fetched, say that explicitly and
|
|
1186
|
-
lower confidence instead of presenting a precise estimate.
|
|
68
|
+
After the user pastes a URL/domain, retain it as `senderLinkedinUrl` or the
|
|
69
|
+
resolved `clientProspectId` input for `create_campaign`. Use one lightweight
|
|
70
|
+
profile/company lookup before strategy questions. If multiple product lines or
|
|
71
|
+
offers are plausible, ask one campaign-focus choice before buyer/offer/proof.
|
|
1187
72
|
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
the user sees which posts are being tested. Then sample engagers, show ICP-fit
|
|
1192
|
-
rate as `n/N` plus percentage/range, convert that to good-fit prospects per 100
|
|
1193
|
-
engagers, estimate average reachable engagers per right-content post, apply a
|
|
1194
|
-
conservative dedupe/cleanup factor, calculate required engagers to scrape,
|
|
1195
|
-
calculate good-fit prospects per post, then calculate how many right-content
|
|
1196
|
-
posts are needed to reach the source target good-fit lead count. Select/promote
|
|
1197
|
-
only enough right-content posts to hit that source target; do not scrape every
|
|
1198
|
-
promoted sample post by default. If the first sample is good but volume is low,
|
|
1199
|
-
say how many more posts would be needed and offer the Sales Nav/Prospeo scale
|
|
1200
|
-
alternative instead of recommending an under-sized source as if it can produce
|
|
1201
|
-
the default 300 good-fit source target.
|
|
73
|
+
Do not call `list_senders`, do not infer the campaign from connected senders,
|
|
74
|
+
and do not show a sender picker during setup. Sender availability belongs only
|
|
75
|
+
to Settings after message approval and review-batch validation.
|
|
1202
76
|
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
77
|
+
Use `research-sender` for concise identity/proof research and call
|
|
78
|
+
`complete_sender_research` before shell creation. If WebSearch is unavailable,
|
|
79
|
+
use the available Sellable profile/company/post tools and carry explicit proof
|
|
80
|
+
gaps into the brief.
|
|
1206
81
|
|
|
1207
|
-
|
|
1208
|
-
describe a generic TAM estimate or pretend the rows came from Sales Nav/Prospeo
|
|
1209
|
-
discovery. For supplied domain/account lists, explain that domains are account
|
|
1210
|
-
constraints and include the actual people sampled from those accounts. If the
|
|
1211
|
-
domain-constrained people sample returns zero or too few usable rows, route to
|
|
1212
|
-
`revise-leads` / `confirm-with-user`; never silently remove the domain
|
|
1213
|
-
constraint.
|
|
82
|
+
## Structured Questions
|
|
1214
83
|
|
|
1215
|
-
|
|
1216
|
-
|
|
84
|
+
Use the host-native structured question gate (`request_user_input` or
|
|
85
|
+
AskUserQuestion) only for bounded choices:
|
|
1217
86
|
|
|
1218
|
-
|
|
1219
|
-
|
|
87
|
+
- campaign focus when the identity has multiple plausible offers
|
|
88
|
+
- source approval or source revision
|
|
89
|
+
- use filters vs skip filters
|
|
90
|
+
- approve message vs revise message
|
|
91
|
+
- sender/sequence/launch choices at Settings
|
|
1220
92
|
|
|
1221
|
-
|
|
93
|
+
Never use it to collect open text, pasted URLs, domains, CSV contents, or
|
|
94
|
+
custom instructions. Ask those in normal chat. Keep `Other / custom` available
|
|
95
|
+
when a bounded choice needs an escape hatch.
|
|
1222
96
|
|
|
1223
|
-
|
|
1224
|
-
`lead-sample.json` as debug context. Filter/rubric saving happens after
|
|
1225
|
-
`workflowTableId` exists from the bounded import. The durable write is
|
|
1226
|
-
`save_rubrics({ campaignOfferId, leadScoringRubrics }) after the campaign table
|
|
1227
|
-
exists`; `lead-filter.md` and `rubric.json` remain debug outputs.
|
|
97
|
+
## Watch Link And Narration
|
|
1228
98
|
|
|
1229
|
-
|
|
1230
|
-
|
|
99
|
+
The first campaign shell is created before lead import so the user can watch
|
|
100
|
+
the work. When `create_campaign` returns `watchUrl`, print it directly and tell
|
|
101
|
+
the user to Command-Enter or click it. Never call browser-opening tools,
|
|
102
|
+
Computer Use, shell `open`, or in-app browser automation just because a watch
|
|
103
|
+
link exists.
|
|
1231
104
|
|
|
1232
|
-
|
|
105
|
+
Every watched step switch must call:
|
|
1233
106
|
|
|
1234
|
-
|
|
1235
|
-
|
|
107
|
+
```text
|
|
108
|
+
update_campaign({ campaignId, currentStep, watchNarration })
|
|
109
|
+
```
|
|
1236
110
|
|
|
1237
|
-
|
|
111
|
+
`watchNarration` must say what just happened, the current visible state, the
|
|
112
|
+
agent intent, and the next user action. Do not mention MCP, prompt chunks, file
|
|
113
|
+
paths, local artifacts, or internal worker mechanics in customer-facing watch
|
|
114
|
+
copy.
|
|
1238
115
|
|
|
1239
|
-
|
|
1240
|
-
history: buyer role, wrong-function exclusions, company-type exclusions,
|
|
1241
|
-
competitor/vendor exclusions, geography, company size, and active-role status
|
|
1242
|
-
- treat right role/function, right seniority/authority, account/channel fit,
|
|
1243
|
-
economic capacity, competitor/vendor exclusion, and active current-role status
|
|
1244
|
-
as table-stakes buyer-quality gates; include geography/market whenever budget,
|
|
1245
|
-
channel adoption, language, compliance, or delivery assumptions depend on it
|
|
1246
|
-
- customize the concrete thresholds for those gates to the client's offer,
|
|
1247
|
-
market, price point, delivery model, and competitor landscape; the invariant
|
|
1248
|
-
is that every passing lead should be worth the user's time if they reply
|
|
1249
|
-
- do not turn "shown interest", post engagement, Signals source, recent posting,
|
|
1250
|
-
provider source, or first-send priority into a production filter; those are
|
|
1251
|
-
discovery or messaging context, not proof the lead is qualified
|
|
1252
|
-
- use the actual lead sample to identify repeated false positives
|
|
1253
|
-
- prefer required keep/exclude rules over a broad scoring stack
|
|
1254
|
-
- allow at most one optional/supporting rule when it materially helps later
|
|
1255
|
-
messaging or prioritization
|
|
1256
|
-
- judge each proposed rule against the sample, report pass rate, and call out
|
|
1257
|
-
whether the rule is truly necessary or should be removed
|
|
1258
|
-
- make every accepted filter directly translatable into production
|
|
1259
|
-
`LeadScoringRubric` rows (`checkName`, `description`, `criterion`, `reason`,
|
|
1260
|
-
`isRequiredCheck`, `allowPartialCredit`, `strictMatching`)
|
|
1261
|
-
- do not accept a filter that cannot be evaluated from `lead-sample.json`,
|
|
1262
|
-
provider row fields, enrichment, or normal public research
|
|
1263
|
-
- derive `rubric.json` from the final `lead-filter.md` rules only when a
|
|
1264
|
-
machine-readable sidecar is needed downstream
|
|
1265
|
-
- continue with `lead-filter.md` as the source of truth when `rubric.json`
|
|
1266
|
-
cannot be written or parsed
|
|
1267
|
-
- if `rubric.json` is omitted, keep the filter concise enough that a 2-5 item
|
|
1268
|
-
production rubric can be compiled from it without inventing new rules
|
|
1269
|
-
- write `lead-filter.md` user-facing first: decision, who we keep, who we
|
|
1270
|
-
exclude, what the sample showed, pass rate, recommendation
|
|
1271
|
-
- include `Implementation Details` inside `lead-filter.md` whenever the status
|
|
1272
|
-
is confirmed; this is where production rubric fields belong
|
|
1273
|
-
- `Implementation Details` must be a fenced JSON object with
|
|
1274
|
-
`leadScoringRubrics` so downstream can parse/save the rules without
|
|
1275
|
-
inference
|
|
1276
|
-
- do not write message artifacts from the filter path; filter-leads owns lead
|
|
1277
|
-
quality and production rubrics only
|
|
116
|
+
## Lead Source
|
|
1278
117
|
|
|
1279
|
-
|
|
118
|
+
Default source order when the user has not supplied a source:
|
|
1280
119
|
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
- `Sample False Positives`
|
|
1286
|
-
- `Optional Supporting Rule` only when one is clearly justified
|
|
1287
|
-
- `Pass Rate`
|
|
1288
|
-
- `Recommendation`
|
|
1289
|
-
- `Implementation Details`
|
|
120
|
+
1. LinkedIn post engagement / Signal Discovery
|
|
121
|
+
2. Sales Nav recent activity
|
|
122
|
+
3. broader Sales Nav role/title filters
|
|
123
|
+
4. Prospeo account/contact expansion
|
|
1290
124
|
|
|
1291
|
-
|
|
1292
|
-
|
|
125
|
+
Call `get_source_scout_registry` before source scouting. Source scouting is
|
|
126
|
+
sequential by default. Run `source-scout-linkedin-engagement`,
|
|
127
|
+
`source-scout-sales-nav`, and `source-scout-prospeo-contact` in parallel only
|
|
128
|
+
when the user explicitly requested source comparison, a prior lane failed, or
|
|
129
|
+
the first viable lane is borderline and a cheap fallback check is needed.
|
|
1293
130
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
-
|
|
1298
|
-
- `reason`
|
|
1299
|
-
- `isRequiredCheck`
|
|
1300
|
-
- `allowPartialCredit`
|
|
1301
|
-
- `strictMatching`
|
|
131
|
+
No leads import until the user approves the source. A source recommendation
|
|
132
|
+
must show concrete evidence: source lane, filters or recipe, raw volume, sample
|
|
133
|
+
size, sampled fits as n/N plus percentage/range, estimated usable prospects,
|
|
134
|
+
cleanup risk, runner-up, and what approval authorizes.
|
|
1302
135
|
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
false-positive families into one exclusion criterion, and keep role fit as its
|
|
1307
|
-
own explicit criterion. Keep raw rubric flags out of the top user-facing
|
|
1308
|
-
sections.
|
|
136
|
+
Supplied profile CSVs, company/domain CSVs, pasted domains, and existing
|
|
137
|
+
Sellable lead lists are supported, but keep provider mechanics out of the first
|
|
138
|
+
customer-facing source-choice labels.
|
|
1309
139
|
|
|
1310
|
-
|
|
140
|
+
## Post-Lead Workstreams
|
|
1311
141
|
|
|
1312
|
-
-
|
|
1313
|
-
|
|
1314
|
-
|
|
142
|
+
After `confirm_lead_list` imports a non-empty bounded review batch and
|
|
143
|
+
`get_rows_minimal({ tableId: workflowTableId })` proves rows exist, call
|
|
144
|
+
`get_post_find_leads_scout_registry`. The filter and message branches use live
|
|
145
|
+
CampaignOffer/source/table state as the source of truth. Debug markdown/json
|
|
146
|
+
artifacts are optional only.
|
|
1315
147
|
|
|
1316
|
-
|
|
148
|
+
Lead Fit Builder persists production rubrics with `save_rubrics` when filters
|
|
149
|
+
are enabled. It must not require `brief.md`, `lead-review.md`, or
|
|
150
|
+
`lead-sample.json`.
|
|
1317
151
|
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
parent-thread fallback. The worker and fallback must load the full
|
|
1321
|
-
`generate-messages` prompt with `get_subskill_prompt` and use it as the drafting
|
|
1322
|
-
contract. The small safety-gate reference is only a supplemental approval
|
|
1323
|
-
check, not a replacement for the long message workflow:
|
|
152
|
+
Message Draft Builder is `post-find-leads-message-scout`. It must load the full
|
|
153
|
+
message prompt:
|
|
1324
154
|
|
|
155
|
+
```text
|
|
156
|
+
get_subskill_prompt({ subskillName: "generate-messages", offset, limit }) until hasMore=false
|
|
1325
157
|
```
|
|
1326
|
-
mcp__sellable__get_subskill_prompt({ subskillName: "generate-messages", offset, limit }) until hasMore=false
|
|
1327
|
-
mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-safety-gate.md" })
|
|
1328
|
-
```
|
|
1329
|
-
|
|
1330
|
-
Use campaign state, campaign brief content, selected source state, and the
|
|
1331
|
-
selected/imported review-batch rows as the source of truth. Do not read
|
|
1332
|
-
`brief.md`, `lead-review.md`, or `lead-sample.json` as required state in the
|
|
1333
|
-
normal live campaign path; those files are optional debug context only. If the
|
|
1334
|
-
long prompt plus safety gate cannot safely approve the draft, stop at
|
|
1335
|
-
`revise-messaging` with the exact failure.
|
|
1336
|
-
|
|
1337
|
-
Return compact output to the parent: template recommendation, token fill rules,
|
|
1338
|
-
one rendered sample, concerns, status, basis token, output timestamp/hash, and
|
|
1339
|
-
error or retry detail. The basis must include campaign revision/updatedAt, brief
|
|
1340
|
-
hash, `selectedLeadListId`, `workflowTableId`, bounded review-batch row
|
|
1341
|
-
ids/hash, filter choice, and filter/rubric basis when present. Do not write
|
|
1342
|
-
message cells, enrich rows, attach sequence, or imply send readiness from this
|
|
1343
|
-
background branch.
|
|
1344
|
-
|
|
1345
|
-
Do NOT proceed to Step 4 (message review gate) unless the user has answered
|
|
1346
|
-
filter choice, the watched app is still on Filter Leads while approval is
|
|
1347
|
-
pending, and `message-validation.md` contains the safety-gate required
|
|
1348
|
-
sections, a raw sendable Selected Winner, and an explicit single-first-send
|
|
1349
|
-
PASS. If the draft is not ready, say you are waiting for the Message Draft
|
|
1350
|
-
Builder and do not ask for approval. If the draft worker fails, produces no
|
|
1351
|
-
usable message, or has no known worker status, require retry/regenerate copy
|
|
1352
|
-
instead of approval copy. If
|
|
1353
|
-
`message-validation.md` contains post-accept DM, follow-up, second-touch,
|
|
1354
|
-
cadence, branch, or other sequence-shaped copy, do not summarize it as ready;
|
|
1355
|
-
route back to message-generation and require a single first outbound send.
|
|
1356
|
-
|
|
1357
|
-
There is no normal Use Template vs AI Generated mode question. After rubrics are
|
|
1358
|
-
saved, stay on Filter Leads, wait for and review the Message Draft Builder
|
|
1359
|
-
template, approve/revise it in chat, then write the approved template into the
|
|
1360
|
-
campaign brief. Only then queue enrichment/ICP scoring for the bounded review
|
|
1361
|
-
batch. Prefer at least 2 usable passing rows before moving the watched browser
|
|
1362
|
-
to Messages; if only 1 passes, use weak-sample copy and ask whether to continue,
|
|
1363
|
-
revise, import more, or skip filters.
|
|
1364
|
-
|
|
1365
|
-
Product Generate Message cells should not run from the background template path
|
|
1366
|
-
until template/token rules are approved.
|
|
1367
158
|
|
|
1368
|
-
|
|
1369
|
-
Message Template` with `{{...}}` tokens before any Generate Message cascade is
|
|
1370
|
-
queued. The message review shows one concrete filled sample for the user, but
|
|
1371
|
-
the durable template lives in `CampaignOffer.campaignBrief`.
|
|
159
|
+
It may also load the supplemental approval checklist:
|
|
1372
160
|
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
The full tail detail (~17k chars: MANDATORY TOOL ORDER, auto-execute-leads, validate-sample loop, auto-execute-messaging, awaiting-user-greenlight, threshold-trip logging, tail hard rules) lives in a dedicated on-demand subskill to keep this entry prompt fast to load.
|
|
1376
|
-
|
|
1377
|
-
Before any auto-execute or validate-sample step, **load the dedicated tail subskill verbatim**:
|
|
1378
|
-
|
|
1379
|
-
```
|
|
1380
|
-
mcp__sellable__get_subskill_prompt({ subskillName: "create-campaign-v2-tail" })
|
|
161
|
+
```text
|
|
162
|
+
get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-safety-gate.md" })
|
|
1381
163
|
```
|
|
1382
164
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
165
|
+
Do not load the full `generate-messages` prompt in the create-campaign parent
|
|
166
|
+
thread unless you are executing the parent-thread fallback for that branch.
|
|
167
|
+
|
|
168
|
+
## Hard Gates
|
|
169
|
+
|
|
170
|
+
- Do not call `create_campaign` until identity research and the brief are ready.
|
|
171
|
+
- Do not call `import_leads` or `confirm_lead_list` until the lead source is
|
|
172
|
+
approved.
|
|
173
|
+
- Do not queue enrichment, ICP scoring, filtering, or product Generate Message
|
|
174
|
+
cells until the review batch exists and the required message/filter approvals
|
|
175
|
+
are complete.
|
|
176
|
+
- Do not call `check_rubric`; persist production rubrics with `save_rubrics`.
|
|
177
|
+
- Do not call `start_campaign` until the user explicitly confirms launch after
|
|
178
|
+
Settings, sender, sequence, and final review.
|
|
179
|
+
- Do not use local files as durable state in normal runs.
|
|
180
|
+
|
|
181
|
+
## References
|
|
182
|
+
|
|
183
|
+
Load references only when needed:
|
|
184
|
+
|
|
185
|
+
- `references/watch-link-handoff.md` for watch-link recovery and handoff copy.
|
|
186
|
+
- `references/watch-guide-narration.md` for watched-step narration.
|
|
187
|
+
- `references/lead-validation-preview.md` for legacy/debug preview shapes.
|
|
188
|
+
- `references/filter-leads.md` for rubric design and `save_rubrics` rules.
|
|
189
|
+
- `references/message-review-safety-gate.md` for final message approval checks.
|
|
190
|
+
- `references/step-13-import-leads.md` before review-batch import.
|
|
191
|
+
- `references/sample-validation-loop.md` before review-batch validation.
|
|
192
|
+
- `references/final-handoff-contract.md` for Settings, sender, sequence, and
|
|
193
|
+
start.
|