@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.
Files changed (33) hide show
  1. package/agents/post-find-leads-filter-scout.md +19 -25
  2. package/agents/post-find-leads-message-scout.md +21 -0
  3. package/agents/registry.json +9 -16
  4. package/agents/source-scout-linkedin-engagement.md +2 -2
  5. package/dist/engage-memory.d.ts +13 -0
  6. package/dist/engage-memory.js +129 -34
  7. package/dist/identity-compiler.d.ts +119 -0
  8. package/dist/identity-compiler.js +344 -0
  9. package/dist/identity-memory.d.ts +49 -0
  10. package/dist/identity-memory.js +89 -0
  11. package/dist/index-dev.js +0 -0
  12. package/dist/index.js +0 -0
  13. package/dist/tools/bootstrap.js +1 -1
  14. package/dist/tools/engage-memory.js +2 -2
  15. package/dist/tools/navigation.js +3 -0
  16. package/dist/tools/prompts.d.ts +1 -4
  17. package/dist/tools/prompts.js +3 -3
  18. package/package.json +1 -1
  19. package/skills/craft-message/SKILL.md +13 -4
  20. package/skills/create-campaign/references/brief-template.md +2 -1
  21. package/skills/create-campaign-v2/SKILL.md +150 -1342
  22. package/skills/create-campaign-v2/core/flow.v2.json +471 -1970
  23. package/skills/create-post/SKILL.md +54 -9
  24. package/skills/engage/SKILL.md +37 -15
  25. package/skills/engage/core/README.md +18 -12
  26. package/skills/generate-messages/SKILL.md +15 -5
  27. package/skills/interview/SKILL.md +183 -89
  28. package/skills/interview/references/anti-ai-audit.md +101 -0
  29. package/skills/interview/references/compiler-schema.md +94 -0
  30. package/skills/interview/references/legacy-linkedin-interview.md +118 -0
  31. package/skills/interview/references/question-bank.md +123 -0
  32. package/skills/interview/references/reference-curation.md +68 -0
  33. 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 with chained Phase 84 artifacts: create a watchable campaign shell with a v1 brief, attach the source with campaignId, import the first 15-row review batch, save rubrics and approved message template, then queue the review cascade and hand off to settings/sequence/start.
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
- <role>
10
- You are the create-campaign-v2 orchestrator. Your job is to execute the
11
- configured `core/flow.v2.json` state machine from scratch: (1) interview the
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
- <objective>
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
- .sellable/create-campaign-v2/drafts/{workspace-slug}/{campaign-slug}/
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
- </files>
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
- - `brief-review` asks whether to approve the rendered campaign brief before
734
- Find Leads starts. Do not skip this by inferring approval from setup
735
- answers.
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
- After the user approves a lead source, the approved provider must remain the
1158
- active watched provider before any materialization work starts. Immediately
1159
- call `update_campaign` again if needed with the approved `leadSourceProvider`
1160
- and matching `currentStep` before `lookup_sales_nav_filter`,
1161
- `get_provider_prompt`, `search_sales_nav`, `search_prospeo`, `import_leads`, or
1162
- `confirm_lead_list`. For example, if the user approves Sales Nav while the
1163
- browser is still showing Signal Discovery, set `leadSourceProvider: "sales-nav"`
1164
- and `currentStep: "sales-nav"` first so the browser switches to the Sales Nav
1165
- lane and the user can watch the approved source progress. Do not set
1166
- `currentStep: "confirm-lead-list"` before `import_leads` returns the lead-list
1167
- table/job id; `import_leads` moves there after the provider import API starts so
1168
- the import page has progress state when it appears.
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
- If you ask for lead-source approval, the question and choices must name the
1171
- source decision. Prefer `Approve Sales Nav with founder/CEO filters, or use
1172
- warmer Signals posts instead?` over `Approve this lead source?`. Option labels
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
- Do not skip or discard Signals based only on raw post count or vibes. If
1182
- Signals was considered, show the post-level math in chat first so the user can
1183
- see which LinkedIn posts would be scraped, how many engagers each has, how many
1184
- sampled engagers looked like good fits, and roughly how many usable prospects
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
- For Signals, default to a quick capacity test before final recommendation. Pick
1189
- a narrow first sample of fresh, high-density posts, and in campaign-attached
1190
- watch runs promote those posts with `select_promising_posts` before sampling so
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
- Keep discarded paths and full sample rows in the campaign/source decision
1204
- context. In explicit debug/UAT runs they may also be copied into
1205
- `lead-sample.json`. Do not show raw filesystem paths unless the user asks.
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
- For supplied profile CSVs and existing lead lists, `lead-review.md` must not
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
- `lead-sample.json` must be a machine-readable sample that downstream filter
1216
- validation can inspect directly.
84
+ Use the host-native structured question gate (`request_user_input` or
85
+ AskUserQuestion) only for bounded choices:
1217
86
 
1218
- If preview returns zero usable leads, write the rejection evidence, stop the
1219
- chain, and route to `revise-leads`.
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
- ## Step 2: Filter Leads
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
- Read CampaignOffer state first, then `brief.md`, `lead-review.md`, and
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
- This branch can run in parallel with Step 3 once `lead-review.md` and
1230
- `lead-sample.json` exist. It owns lead quality and production rubrics only.
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
- Write:
105
+ Every watched step switch must call:
1233
106
 
1234
- - `lead-filter.md`
1235
- - optional `rubric.json`
107
+ ```text
108
+ update_campaign({ campaignId, currentStep, watchNarration })
109
+ ```
1236
110
 
1237
- Required behavior:
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
- - preserve recurring keep/exclude filter families that show up across campaign
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
- `lead-filter.md` must contain:
118
+ Default source order when the user has not supplied a source:
1280
119
 
1281
- - `Status`
1282
- - `Decision`
1283
- - `Who We'll Keep`
1284
- - `Who We'll Exclude`
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
- When `rubric.json` is emitted, it must use the production rubric shape, not a
1292
- custom sidecar schema:
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
- - `leadScoringRubrics`
1295
- - `checkName`
1296
- - `description`
1297
- - `criterion`
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
- `Implementation Details` must contain a fenced JSON object with
1304
- `leadScoringRubrics`, and that array must contain 2-5 production rubric items
1305
- total. Do not create one rubric row per keep/exclude bullet. Bundle related
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
- Do not:
140
+ ## Post-Lead Workstreams
1311
141
 
1312
- - call `check_rubric`
1313
- - create a second independent scoring design in `rubric.json`
1314
- - emit more than one optional/supporting rule
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
- ## Step 3: Generate Message
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
- Step 3 is the Message Draft Builder path. It is orchestrated by the main thread
1319
- and executed either by the `post-find-leads-message-scout` worker or by the
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
- After the main-chat message approval, update_campaign_brief writes `## Approved
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
- ## Tail (MANDATORY TOOL ORDER + Steps 13-16 + Threshold Trips + Hard Rules)
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
- Follow that prompt verbatim. It contains the canonical MANDATORY TOOL ORDER (read this BEFORE any tail step), all Step 13-16 contracts, threshold-trip logging rules, and tail hard rules.
1384
-
1385
- Do NOT invoke any tail tool (auto_execute_leads, validate_sample, auto_execute_messaging, etc.) without first loading this subskill — the tool order and the threshold-trip checks live there.
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.