@sellable/mcp 0.1.213 → 0.1.215

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 (29) hide show
  1. package/agents/post-find-leads-message-scout.md +190 -151
  2. package/dist/tools/prompts.js +18 -13
  3. package/package.json +1 -1
  4. package/skills/create-campaign/SKILL.md +11 -12
  5. package/skills/create-campaign-brief/references/examples/briefs/superpower.md +3 -3
  6. package/skills/create-campaign-brief/references/phase75-active-runtime-message-pack.md +16 -28
  7. package/skills/create-campaign-v2/SKILL.md +12 -9
  8. package/skills/create-campaign-v2/core/auto-execute.README.md +11 -11
  9. package/skills/create-campaign-v2/core/auto-execute.yaml +4 -4
  10. package/skills/create-campaign-v2/core/flow.v2.json +1 -1
  11. package/skills/create-campaign-v2/references/ai-tells.md +3 -3
  12. package/skills/create-campaign-v2/references/approval-gate-framing.md +9 -9
  13. package/skills/create-campaign-v2/references/escalation-ladder.md +3 -3
  14. package/skills/create-campaign-v2/references/final-handoff-contract.md +3 -3
  15. package/skills/create-campaign-v2/references/gold-standard-message-examples.md +294 -239
  16. package/skills/create-campaign-v2/references/gold-standard-message-patterns.md +13 -9
  17. package/skills/create-campaign-v2/references/gold-standard-message-validation-example.md +4 -4
  18. package/skills/create-campaign-v2/references/lead-validation-preview.md +1 -1
  19. package/skills/create-campaign-v2/references/parallel-critique-protocol.md +10 -10
  20. package/skills/create-campaign-v2/references/sample-validation-loop.md +3 -3
  21. package/skills/create-campaign-v2/references/{thomas-revision-filters.md → sellable-cleanup-rules.md} +13 -12
  22. package/skills/create-campaign-v2/references/step-15-re-cascade.md +1 -1
  23. package/skills/create-campaign-v2/references/thomas-variant-selection.md +1 -1
  24. package/skills/create-campaign-v2/references/validation-criteria.md +16 -13
  25. package/skills/create-campaign-v2-tail/SKILL.md +7 -7
  26. package/skills/create-campaign-v2-validation/SKILL.md +17 -8
  27. package/skills/generate-messages/SKILL.md +157 -93
  28. package/skills/research/config.json +9 -0
  29. package/skills/create-campaign-v2/references/gold-standard-runtime-message-pack.md +0 -252
@@ -39,7 +39,7 @@ hey {{first name}},
39
39
 
40
40
  saw you in a few conversations around {{topic}}, so hope this is relevant.
41
41
 
42
- if preventive health is anywhere near the benefits plan at {{company}}, Superpower may be worth a look.
42
+ if preventive health is anywhere near the benefits plan at {{company}}, Superpower helps the team spot risk earlier.
43
43
 
44
44
  it screens for 1,000+ conditions from a single blood draw and surfaces risks before they become claims.
45
45
 
@@ -72,7 +72,7 @@ hey susana,
72
72
 
73
73
  saw you in a few conversations around self-insured health plans, so hope this is relevant.
74
74
 
75
- if preventive health is anywhere near the benefits plan at Quantum Health, Superpower may be worth a look.
75
+ if preventive health is anywhere near the benefits plan at Quantum Health, Superpower helps the team spot risk earlier.
76
76
 
77
77
  it screens for 1,000+ conditions from a single blood draw and surfaces risks before they become claims.
78
78
 
@@ -104,7 +104,7 @@ hey princess,
104
104
 
105
105
  saw you in a few conversations around employee wellness programs, so hope this is relevant.
106
106
 
107
- if preventive health is anywhere near the benefits plan at Marriott, Superpower may be worth a look.
107
+ if preventive health is anywhere near the benefits plan at Marriott, Superpower helps the team spot risk earlier.
108
108
 
109
109
  it screens for 1,000+ conditions from a single blood draw and surfaces risks before they become claims.
110
110
 
@@ -1,4 +1,4 @@
1
- # Phase 75 Active Runtime Message Pack
1
+ # Active Runtime Message Pack
2
2
 
3
3
  This is the narrow message inspiration pack for `create-campaign-brief`.
4
4
 
@@ -138,22 +138,26 @@ b) I send you our B2B Ads Arsenal — ad templates, playbooks, and case studies
138
138
 
139
139
  Why included:
140
140
 
141
- - strongest concrete operational offer
142
- - easy to picture the output
143
- - why it works: the pain is tactile, the mechanism is easy to visualize, and the
144
- CTA lets the buyer test the product with their own real input instead of
145
- committing to a generic call
141
+ - strongest signal-led honest-operator foodservice motion
142
+ - concrete buyer pain before product category
143
+ - why it works: the source bridge is low-certainty, the mechanism connects real
144
+ operating objects, and the CTA names a useful conversation instead of asking
145
+ for a generic call
146
146
 
147
147
  ```md
148
- hey {{first_name}},
148
+ Hey Mohamed,
149
+
150
+ Found you in a thread about food cost margins, so may be off, but this seemed relevant.
149
151
 
150
- this might not apply but if you're still rebuilding menu plans by hand every time a rotation changes, there's a way to skip that whole step.
152
+ Bulk costing gets messy when recipes, portions, and vendor prices live apart.
151
153
 
152
- we built a tool that takes a menu from whatever format it's in and just... builds the whole plan. recipes, purchasing, stations, all connected. no more starting from scratch every cycle.
154
+ Galley is a Culinary Resource Planning platform for foodservice teams.
153
155
 
154
- works best for {{company_team_type}} running rotations across a bunch of locations where every menu change turns into hours of work nobody has time for.
156
+ It keeps recipes, ingredient costs, and menu margins connected - where purchasing and production can work from the same numbers.
155
157
 
156
- easiest way to see if it's worth a look is to try it with one of your actual menus. happy to set that up or I can send a 2-min video instead.
158
+ Open to a quick call on recipe costing and margin visibility?
159
+
160
+ P.S. 2,400+ kitchens already use Galley - with a 4.9 average rating :)
157
161
  ```
158
162
 
159
163
  ### Clover
@@ -225,7 +229,7 @@ Hey {{first_name}},
225
229
 
226
230
  saw you in a few conversations around {{topic}}, so hope this is relevant.
227
231
 
228
- if preventive health is anywhere near the benefits plan at {{company}}, Superpower may be worth a look.
232
+ if preventive health is anywhere near the benefits plan at {{company}}, Superpower helps the team spot risk earlier.
229
233
 
230
234
  it screens for 1,000+ conditions from a single blood draw and surfaces risks before they become claims.
231
235
 
@@ -233,19 +237,3 @@ basically your team gets to see what's coming instead of only reacting to it.
233
237
 
234
238
  should i send over the short version?
235
239
  ```
236
-
237
- Locked production variant from the same Superpower campaign:
238
-
239
- ```md
240
- subject: {{company}} + 1,000 biomarkers + 24/7 care team
241
-
242
- hey {{first_name}},
243
-
244
- curious how you're thinking about preventative health + benefits innovation given your work at {{company}}.
245
-
246
- we provide companies direct access to 100+ biomarker lab testing and screen 1,000+ conditions for every employee.
247
-
248
- then we drive behaviour change with a 24/7 care team.
249
-
250
- open to a 15 min call to learn more, or should i send over a short overview first?
251
- ```
@@ -4,9 +4,9 @@ description: compact JSON-gated shell-first Sellable campaign flow through sourc
4
4
  visibility: internal
5
5
  ---
6
6
 
7
- # Create Campaign v2
7
+ # Create Campaign Workflow
8
8
 
9
- fast entry point. Run the active state machine in `core/flow.v2.json`;
9
+ Fast entry point. This is the fast entry point. Run the active state machine in `core/flow.v2.json`;
10
10
  load deeper references only at the stage that needs them.
11
11
  Load the compact flow for exact gates:
12
12
 
@@ -309,7 +309,7 @@ background.
309
309
 
310
310
  Codex: YOLO counts as permission for this one post-import worker. If no
311
311
  permission, ask once after filter choice. Use generic `gpt-5.5` / `xhigh`
312
- Message Drafting if needed. Never draft in parent silently.
312
+ Message Drafting if needed.
313
313
 
314
314
  If the user critiques or edits the template before `approve-message`, route the
315
315
  feedback back to Message Drafting with current `messageDraftRecommendation`,
@@ -322,18 +322,21 @@ and validation before approval also belong to Message Drafting, but validation
322
322
  is an internal gate. Do not render `renderedFallbackSample`, `concerns`, or a
323
323
  full `qaReceipt` in the normal happy path.
324
324
 
325
- Load:
325
+ Run `post-find-leads-message-scout` as Message Draft Builder when exposed. It
326
+ must load:
326
327
 
327
328
  ```text
328
329
  get_subskill_prompt({ subskillName: "generate-messages" })
329
- get_subskill_asset(...) for every asset in generate-messages Reference Asset Loading
330
+ get_subskill_asset(...) for every required message asset named by generate-messages Mode 0
330
331
  get_subskill_prompt({ subskillName: "create-campaign-v2-validation" })
331
332
  ```
332
333
 
333
- Do not use any alternate or examples-only message prompt. Do not render message
334
- review until `messageDraftRecommendation` proves current campaign/table basis
335
- and shows whether it came from Message Drafting or an explicitly approved inline
336
- fallback.
334
+ After candidate generation/revision and before returning `ready`, Message Draft
335
+ Builder must load `create-campaign-v2-validation` through MCP as the final gate.
336
+ No alternate, examples-only, or local-artifact prompt. If the agent cannot
337
+ launch, the parent fallback runs the same gate from live state. Render review
338
+ only after `messageDraftRecommendation` proves current campaign/table basis.
339
+ Handoff: labeled Markdown, not raw JSON.
337
340
 
338
341
  ## Hard Gates
339
342
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  This file narrates `auto-execute.yaml`. The YAML is the source of truth; this
4
4
  README explains intent, tuning guidance, and how each knob affects the
5
- Plan 85-02 autonomous tail.
5
+ autonomous tail.
6
6
 
7
7
  ## When this file is loaded
8
8
 
@@ -24,7 +24,7 @@ into the campaign).
24
24
  confirmed source rows into the campaign. The tail MUST NOT exceed this cap
25
25
  before the message template is approved and at least one generated passing
26
26
  message is reviewed.
27
- - **`provider`** — Inherited from the Phase 84 commit decision (saved in
27
+ - **`provider`** — Inherited from the approved source decision (saved in
28
28
  the committed brief / campaign metadata). Present here so the tail can
29
29
  narrate which provider it's running against; it does NOT override the
30
30
  committed provider.
@@ -54,8 +54,8 @@ into the campaign).
54
54
  proceeds.
55
55
  Default `strict` because live campaign state shouldn't ship messages
56
56
  with unresolved templating.
57
- - **`critique.enabled`** — Plan 85-03 feature flag for the message
58
- critique pass. Plan 85-02 reads the flag but never flips it; it
57
+ - **`critique.enabled`** — Feature flag for the optional message
58
+ critique pass. The plain campaign tail reads the flag but never flips it; it
59
59
  stays false by default. Only flip to `true` after dry-running the
60
60
  critique protocol against a real sample and confirming the token
61
61
  contract still holds on the rewritten output. See
@@ -77,7 +77,7 @@ into the campaign).
77
77
  voice). Each critic returns structured JSON the synthesis step can
78
78
  merge. Do NOT add free-form critics; stay on the three groups.
79
79
  - **`critique.synthesis.enforceFinalizerPass`** — When `true`, the
80
- synthesizer re-runs the Phase 84 finalizer pass on its rewrite.
80
+ synthesizer re-runs the offline-validation finalizer pass on its rewrite.
81
81
  This is the last guardrail against critic-introduced token drift.
82
82
  Default stays `true`.
83
83
  - **`critique.opus.enabled`** — Flag gating Opus refinement
@@ -154,20 +154,20 @@ logs and adjust:
154
154
  conditions that short-circuit the tail.
155
155
  - `references/final-handoff-contract.md` — the dual greenlight channel
156
156
  that takes Step 16 into a running campaign.
157
- - `references/parallel-critique-protocol.md` — Plan 85-03 Step 15
157
+ - `references/parallel-critique-protocol.md` — optional Step 15
158
158
  critique protocol: bounded sample, parallel critics, synthesis,
159
159
  budget caps, and token-contract enforcement.
160
- - `references/thomas-variant-selection.md` — Plan 85-03 rules for
160
+ - `references/thomas-variant-selection.md` — rules for
161
161
  which rows earn an Opus refinement rewrite.
162
- - `references/thomas-revision-filters.md` — the positive-target and
162
+ - `references/sellable-cleanup-rules.md` — the positive-target and
163
163
  automatic-revision filters that gate any critique rewrite.
164
164
 
165
165
  ## Flipping `messaging.critique.enabled` to true (dry-run protocol)
166
166
 
167
167
  The critique flag stays `false` by default because an enabled critique
168
168
  pass invents new tokens + costs ~$2 per sample pass — both of which
169
- can silently degrade a live campaign if the protocol isn't solid. Plan
170
- 85-02 ships the protocol; flipping the default requires dry-run
169
+ can silently degrade a live campaign if the protocol isn't solid. Flipping
170
+ the default requires dry-run
171
171
  evidence.
172
172
 
173
173
  ### Required evidence before flipping default
@@ -186,7 +186,7 @@ evidence.
186
186
  re-evaluate per archetype.
187
187
 
188
188
  3. **Token contract finalizer passes on every synthesis output.** The
189
- finalizer pass (Phase 84 token contract) is the last guardrail
189
+ finalizer pass (offline-validation token contract) is the last guardrail
190
190
  against critic-introduced token drift. If any synthesis output
191
191
  fails the finalizer in dry-run, the protocol is not safe to flip.
192
192
 
@@ -1,4 +1,4 @@
1
- # Autonomous tail configuration for create-campaign-v2 (Plan 85-02)
1
+ # Autonomous tail configuration for create-campaign-v2
2
2
  #
3
3
  # This file controls the shell-first review-batch tail that runs AFTER the
4
4
  # campaign shell already has the approved source, saved rubrics, and approved
@@ -43,7 +43,7 @@ messaging:
43
43
  # relaxed = warn but allow. Default is strict for live campaign state.
44
44
  tokenContract: strict
45
45
  critique:
46
- # Feature flag for the message critique pass shipped in Plan 85-03.
46
+ # Feature flag for the optional message critique pass.
47
47
  # Stays false by default. Flip to true only after the critique
48
48
  # protocol has been dry-run against a real sample.
49
49
  enabled: false
@@ -82,8 +82,8 @@ messaging:
82
82
  # being persisted — synthesis never ships a message that invents
83
83
  # tokens, proof, or personalization.
84
84
  model: synthesizer
85
- # When true, the synthesis step is required to re-run the Phase
86
- # 84 finalizer pass on its output. The finalizer is the last
85
+ # When true, the synthesis step is required to re-run the
86
+ # offline-validation finalizer pass on its output. The finalizer is the last
87
87
  # guardrail against critic-introduced token drift.
88
88
  enforceFinalizerPass: true
89
89
  opus:
@@ -1 +1 @@
1
- {"version":"v2.1-compact","workflow":"create-campaign-v2","principle":"CampaignOffer state/watch link are canonical. Create shell, approve Find Buyers Plan and Start Import, confirm source rows, process first slice, approve filters/message, then run bounded cascade before Settings and explicit start.","normalCustomerPath":"Use campaign state, MCP responses, and concise watchNarration. Do not create, read, link, or surface local draft files. Print the exact tokenized create_campaign.watchUrl only once at the initial brief handoff.","legacyCompatibility":{"validationSubskill":"create-campaign-v2-validation","tailSubskill":"create-campaign-v2-tail","rule":"Legacy validation/rehearsal files are opt-in diagnostics only and are not active flow gates."},"commitGateChoices":["approve","revise-brief","revise-leads","revise-rubric","revise-messaging","abort"],"canonicalStateFields":["campaignId","watchUrl","campaignBrief","currentStep","watchNarration","interactionMode","providerSearchAssociation","selectedLeadListId","workflowTableId","filterChoice","leadScoringRubrics","messageDraftRecommendation","approvedMessageTemplate","senderIds","sequenceTemplate","runningState"],"watchNarrationTransitionContract":{"rule":"Every watched currentStep switch must include fresh watchNarration.","requiredFields":["stage","headline","visibleState","agentIntent","nextAction"],"copyMustInclude":["what just happened","current visible page/state","next user action"],"appliesToTools":["create_campaign","update_campaign","attach_recommended_sequence","start_campaign"],"oneTimeWatchLinkPolicy":"After the initial brief handoff, customer-facing turns must not print another watch link unless the user asks or link recovery is needed."},"lazyReferences":{"watch":["references/watch-link-handoff.md","references/watch-guide-narration.md"],"source":["references/lead-validation-preview.md","references/step-13-import-leads.md"],"filter":["references/filter-leads.md"],"message":[],"tail":["references/sample-validation-loop.md","references/step-15-re-cascade.md","references/final-handoff-contract.md"]},"safetyBoundaries":["Do not call list_senders before Settings after message approval.","Do not import leads until Start Import is approved.","Do not queue cells until confirmed source rows exist in the campaign and the message/filter gates are satisfied.","Do not call start_campaign until the user explicitly confirms launch.","Do not use local files as durable state in normal customer runs."],"yoloMode":{"triggerPhrases":["yolo","--yolo","mode=yolo","autopilot","use best guesses","use best estimates","answer for me","just run it","yolo autopilot"],"identityRequestOnlyWhenMissing":true,"operatorDirectionsRule":"Treat freeform directions supplied at invocation or later as durable operator directions; newest conflicting direction wins.","setInteractionModeAfterCampaignCreate":"autonomous","autoSelectsPreLaunchChoices":["campaign focus","brief approval","source plan","Start Import approval","filters vs skip filters","filter rubric approval","message template approval when recommendation is approve-message","generated message review when quality floor passes","sender selection when exactly one connected sender is safe"],"mustPauseFor":["missing LinkedIn profile URL or handle","missing credentials or required data","ambiguous choice with no reasonable estimate","source/message/filter quality floor failure","final live launch confirmation"],"neverAutoStart":true},"steps":[{"id":"bootstrap","label":"Bootstrap","onEnter":[{"tool":"bootstrap_create_campaign","requiredValues":{"flowVersion":"v2"}},{"tool":"get_subskill_prompt","requiredValues":{"subskillName":"create-campaign-v2"}}],"allowedTools":["bootstrap_create_campaign","get_auth_status","get_active_workspace","get_subskill_prompt","AskUserQuestion","request_user_input"],"doNotAllow":["create_campaign","list_senders","save_rubrics","import_leads","confirm_lead_list","update_campaign","queue_cells","start_campaign"],"waitFor":"bootstrap_complete","transitions":{"bootstrap_complete":"brief-interview"}},{"id":"brief-interview","label":"Client, offer, research, and brief","onEnter":[{"action":"resolve_campaign_identity_before_strategy_packet","allowedTools":["fetch_company","fetch_linkedin_profile","WebFetch","WebSearch"],"mustNotInferFromNameOnly":true,"doNotPresentSenderPickerBeforeIdentityInference":true,"fallback":"Ask only: \"What is your LinkedIn profile URL or handle?\" Normalize bare handles or `/in/...` paths to `https://www.linkedin.com/in/{handle}/`. If the input is not a profile, ask again for the person profile URL before strategy questions.","requiresLinkedInProfileUrl":true,"doNotAcceptAsIdentityInput":["non-profile URL","company page","company/name-only input without a profile handle"],"acceptsLinkedInProfileHandle":true,"normalizeLinkedInProfileHandleToUrl":true},{"action":"run_campaign_identity_research_before_strategy_packet","target":"research-sender","requiredCompletion":"complete_sender_research","allowedTools":["get_subskill_prompt","fetch_linkedin_profile","fetch_company","fetch_linkedin_posts","fetch_company_posts","WebFetch","WebSearch","complete_sender_research"],"requiredInput":"LinkedIn profile URL or handle"},{"action":"confirm_target_before_strategy_packet","uses":"request_user_input","singleChoice":true,"question":"Who should we target first?","options":["Use Sellable's researched recommendation","Choose a different buyer","I'm not sure yet"],"copyMustInclude":["research basis","recommendation is editable","who to target"],"requiredOption":"Other / custom","neverCollectOpenTextWithStructuredQuestion":true,"skipIf":"user already supplied a clear target or yolo_mode with any reasonable best-estimate target"},{"action":"confirm_current_offer_before_strategy_packet","uses":"request_user_input","question":"What should we pitch to prospects first?","options":["Use Sellable's researched recommendation","Use my current pitch","Shape the pitch together"],"copyMustInclude":["research basis","public LinkedIn research may be stale","recommendation is editable","pitch to prospects"],"skipIf":"user already supplied a clear current offer or yolo_mode with any reasonable researched recommendation"},{"action":"confirm_trust_proof_before_strategy_packet","uses":"request_user_input","singleChoice":true,"question":"What is the strongest credibility signal we can lead with?","options":["Use Sellable's recommended proof","Use customer proof or a case study","Use founder or company credibility"],"copyMustInclude":["build trust with prospects","recommendation is editable","proof to use or avoid"],"requiredOption":"Other / custom","skipIf":"user already supplied clear proof to use or avoid, or yolo_mode with any reasonable researched proof"},{"action":"choose_prospect_source_path_before_strategy_packet","uses":"request_user_input","singleChoice":true,"question":"How should we find prospects?","options":["Find prospects for me","Use a CSV of LinkedIn profiles","Use a CSV of company domains"],"copyMustInclude":["prospects","no one added yet","find prospects for me"],"skipIf":"user already supplied a source path or yolo_mode with any reasonable source path"},{"action":"infer_strategy_packet_in_yolo_mode","when":"yolo_mode","skipStructuredSetupQuestions":true,"inferFields":["buyer segment","offer/CTA","proof to use or avoid","lead source","filter choice","message direction"],"sourceOfTruth":"identity/company lookup plus operator directions","mustStateAssumptionsInBrief":true},{"action":"render_supplied_setup_receipt_before_brief_when_setup_questions_skip","when":"any setup question is skipped because the user already supplied or yolo mode inferred identity, target, offer, proof, or source","output":"normal chat receipt before the campaign brief or watch-link handoff","copyMustInclude":["Accepted LinkedIn input: normalized to the required LinkedIn profile URL.","Offer path: supplied current offer or Sellable's researched recommendation; you can replace it with your current offer."],"copyMustNotInclude":["Campaign Identity"]},{"action":"create_watchable_campaign_shell_with_v1_brief","tool":"create_campaign","requiredFields":["name","campaignBrief","clientProspectId or senderLinkedinUrl","currentStep","watchNarration"],"requiredValues":{"currentStep":"create-offer","watchNarration.stage":"brief"},"capture":["campaignId","watchUrl"],"canonicalStateWrites":["campaignId","watchUrl","campaignBrief","currentStep:create-offer"]},{"action":"surface_campaign_shell_watch_link","watchUrlSource":"create_campaign.watchUrl","requiredWatchUrlShape":"exact create_campaign.watchUrl; direct /campaign-builder/{campaignId}?mode={claude|codex} URL with workspaceId and token","copyMustInclude":["We'll keep building the campaign in this chat.","You can watch it being built in real time in the app here:","I'll ask for your approval whenever I need your expertise or taste before moving forward.","Send changes here."],"immediateNextMainChatLine":"Ask for brief approval now. After approval, say: \"Brief approved. Next, we'll choose where to find buyers. I won't add anyone yet.\"","codexBrowserHandoff":{"openWhenAvailable":false,"printWatchLinkOnly":true,"tellUserCommandEnterOrClick":false,"mustNotUseBrowserAutomation":true,"fallbackMustNotClaimInspection":true},"copyMustAvoid":["bare /campaign-builder/{campaignId} URL","derived watch URL","second Watch link:","Next, we'll choose where to find buyers"],"oneTimeOnly":true}],"allowedTools":["get_subskill_prompt","fetch_company","fetch_company_posts","fetch_linkedin_profile","fetch_linkedin_posts","complete_sender_research","create_campaign","AskUserQuestion","request_user_input"],"doNotAllow":["list_senders","save_rubrics","import_leads","confirm_lead_list","queue_cells","start_campaign"],"waitFor":["campaign_shell_created","brief_ready","confirm_with_user"],"transitions":{"campaign_shell_created":"brief-review","brief_ready":"brief-review","confirm_with_user":"brief-review"}},{"id":"brief-review","label":"Brief review","onEnter":[{"action":"render_brief_inline","minimumVisibleDetail":"campaign direction, buyer, offer, proof, source plan, safety gates","copyMustInclude":["This brief is based on Sellable's research and your answers.","If your site or LinkedIn is stale","Do you agree with this researched campaign direction?"],"copyMustNotInclude":["quoted first-message copy","Message Angle as final proof","This approval covers","does not approve adding people","does not approve scraping posts","selecting a sender","attaching a sequence","Campaign Identity","what should this campaign sell first","sell first","[from you]","[from LinkedIn]","[from website]","[from case study]","[Sellable recommendation]"],"messageHintRule":"If any message-shape hint remains, keep it as non-final bullets and say real examples come after leads are found and filtered.","approvalBoundaryRule":"Keep this gate positive and short. Do not list later steps this approval does not cover; ask approve/revise and then move to choosing where to find buyers.","sectionLabelRule":"Use ## Sender and Company for the person/company context; never render ## Campaign Identity.","skipIf":"the full brief was already rendered in the current shell-creation handoff before create_campaign returned","renderOnceRule":"The brief must be visible exactly once before approval. Do not render it again immediately after shell creation; append the one watch-link handoff and ask the approval question.","copyMustAvoid":["duplicate brief render after shell creation","second Watch link:"]},{"action":"ask_brief_choice","uses":"request_user_input","choices":["Approve brief","Revise brief","Approve + YOLO autopilot setup"],"skipIf":"yolo_mode; auto_continue after rendering assumptions unless brief quality floor fails","question":"Do you agree with this researched campaign direction?","autonomousChoice":"Approve + YOLO autopilot setup","choiceDescriptions":{"Approve + YOLO autopilot setup":"Use best guesses to finish setup and stop before final launch."}}],"requiredCampaignState":["campaignId","watchUrl","campaignBrief","currentStep"],"allowedTools":["AskUserQuestion","request_user_input","update_campaign"],"doNotAllow":["create_campaign","list_senders","import_leads","confirm_lead_list","queue_cells","start_campaign"],"waitFor":["user_brief_confirmed","revise_brief","auto_continue"],"transitions":{"user_brief_confirmed":"find-leads","revise_brief":"brief-interview","auto_continue":"find-leads"}},{"id":"find-leads","label":"Find leads","sourceSelectionFunnel":{"preScoutRecommendationGate":{"required":true,"label":"Find buyers plan approval","mustHappenBefore":["get_provider_prompt","search_signals","search_sales_nav","search_prospeo","fetch_post_engagers"],"show":["buyer groups or places we could check","best place to start","why the right buyers are likely to be there","what signs the next search will check","where to look next if the first place is too thin","what approval authorizes"],"approvalAuthorizes":"looking for the best places to find buyers; no one added yet","explanationMustInclude":["where the right buyers are already talking","why that place fits this campaign","enough likely prospects","what counts as a good sign","where to look next if thin","I won't add anyone yet","choose where to find buyers"],"yoloMode":{"autoApproveRecommendedLane":true,"mustShowAssumedChoice":true,"pauseIfConfidenceLow":true},"customerLanguage":{"readability":"grade-5","requiredHeading":"Find Buyers Plan","prefer":["place to look","best place to start","people to check","prospects","I won't add anyone yet"],"avoid":["lane","source scouting","provider","precision/scale tradeoff","evidence quality","pilot volume","ICP","workflow pain","lead-source scouting","not importing leads"],"termRule":{"buyers":"target market","peopleToCheck":"raw reactions/comments before fit is known","prospects":"likely usable people after fit","leads":"campaign rows"}},"questionOrder":"update_campaign to pick-provider, render ## Find Buyers Plan in normal chat without repeating the watch link, then open the structured approval question; never ask first or show the plan after approval","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"approvalFreshnessRule":"Only an approval question opened after the visible Find Buyers Plan, or an explicit source choice made after that plan, can set source_lane_approved. Do not reuse brief approval or pre-plan provider state."},"defaultWhenSourceUnspecified":["signal-discovery","sales-nav-recent-active","sales-nav-general","prospeo"],"parallelAllowedOnlyWhen":["user explicitly requested source comparison"]},"onEnter":[{"tool":"update_campaign","requiredValues":{"currentStep":"pick-provider","watchNarration.stage":"find-leads","watchNarration.headline":"Review where to find buyers","watchNarration.visibleState":"The app is showing source selection before lead finding starts.","watchNarration.agentIntent":"Codex is explaining where it recommends looking first and where it will look next if that is too thin.","watchNarration.nextAction":"Approve where to look first or choose another place","watchNarration.safety":"Only deciding where to look. No one is added yet."}},{"action":"render_find_buyers_plan_inline","oneShot":true,"requiredPrecondition":"currentStep=pick-provider has been saved with update_campaign","mustHappenAfter":["update_campaign currentStep=pick-provider"],"mustHappenBefore":["ask_find_buyers_plan_choice","get_provider_prompt","search_signals","search_sales_nav","search_prospeo","fetch_post_engagers"],"output":"normal chat text before any request_user_input approval panel","requiredHeading":"Find Buyers Plan","requiredInlineFields":["plain-language buyer groups or places for this campaign","best place to start","why the right buyers are likely to be there","what signs the next search will check","where to look next if the first place is too thin","what approval authorizes"],"copyMustInclude":["Find Buyers Plan","best place to start","I won't add anyone","choose where to find buyers","I won't add anyone yet"],"copyMustAvoid":["lane","source scouting","provider","precision/scale tradeoff","evidence quality","pilot volume","ICP","workflow pain","lead-source scouting","not importing leads","Watch link:","campaign-builder URL","repeat the watch URL"],"approvalBoundary":"Explain what approval authorizes before asking: looking for the best places to find buyers; no one is added yet.","linkPolicy":"Do not include another watch link. The first brief handoff already gave the user the live app URL."},{"action":"ask_find_buyers_plan_choice","uses":"request_user_input","oneShot":true,"requiredPrecondition":"render_find_buyers_plan_inline completed in normal chat after pick-provider state was saved; no earlier approval can satisfy this","skipIf":"source_lane_approved was set by ask_find_buyers_plan_choice after the visible Find Buyers Plan, leadSourceProvider was explicitly chosen by the user after that plan, or yolo_mode auto-selected source_lane_approved after showing the assumed choice","choices":["Start with LinkedIn posts","Start with active LinkedIn profiles","Start with company/contact search","Choose a different place","Pause here"],"approvalChoiceLabelsByProvider":{"signal-discovery":"Start with LinkedIn posts","sales-nav":"Start with active LinkedIn profiles","prospeo":"Start with company/contact search"},"approvalState":"source_lane_approved","copyMustInclude":["Approve this plan for where to find buyers?","Start with LinkedIn posts"],"mustNotHappenBefore":["render_find_buyers_plan_inline"],"approvalStateRule":"Set source_lane_approved here after the visible plan; never from brief approval, generic approval, pre-plan provider state, or artifacts."},{"action":"persist_provider_search_step_before_search","tool":"update_campaign","requiredPrecondition":"source_lane_approved set after the visible Find Buyers Plan approval question","providerCurrentStepMap":{"signal-discovery":"signal-discovery","sales-nav":"sales-nav","prospeo":"prospeo"},"requiredValues":{"leadSourceType":"new","leadSourceProvider":"approved provider","currentStep":"provider-specific current step","watchNarration.stage":"find-leads","watchNarration.headline":"Searching the approved place","watchNarration.safety":"Looking only. No one is added yet."},"mustRunBefore":["search_signals","search_sales_nav","search_prospeo","fetch_post_engagers"]},{"action":"run_parent_thread_source_funnel","requiredPrecondition":"source_lane_approved after visible Find Buyers Plan approval","mode":"parent_thread_inline_sequential","sourceAgents":"forbidden in normal create-campaign","loadsOnlyActiveProviderPrompt":true,"defaultOrder":["signal-discovery","sales-nav-recent-active","sales-nav-general","prospeo"],"stopOnFirstViableUnlessComparisonRequested":true}],"requiredCampaignState":["campaignId","campaignBrief","currentStep"],"allowedTools":["get_provider_prompt","lookup_sales_nav_filter","search_sales_nav","search_prospeo","search_signals","select_promising_posts","fetch_post_engagers","fetch_company","fetch_linkedin_profile","load_csv_linkedin_leads","load_csv_domains","get_rows_minimal","update_campaign","AskUserQuestion","request_user_input","get_campaign_navigation_state"],"doNotAllow":["create_campaign","list_senders","save_rubrics","import_leads","confirm_lead_list","queue_cells","start_campaign","Task","spawn_agent"],"waitFor":["lead_review_ready","revise_brief","confirm_with_user"],"transitions":{"lead_review_ready":"lead-review","revise_brief":"brief-interview","confirm_with_user":"lead-review"}},{"id":"lead-review","label":"Start Import approval","onEnter":[{"action":"show_source_decision_card","requiredInlineFields":["primary source and exact filters/recipe","Start Import action awaiting approval","for Signal Discovery: compact Source Recommendation in plain language with selected posts, people to check, likely prospects, first review, and fallback","for Signal Discovery: recommended scrape post count and target people-to-check volume","first campaign review size, clearly separate from source sampling","runner-up and why it lost","raw volume","sampled people","sampled fits as n/N plus percentage/range","estimated usable prospects","cleanup risk","what happens after Start Import"],"copyMustAvoid":["lead-source scouting","source scouting","headline-fit","engagers needed","execution slice","ICP","good buyers","real buyers","This approval covers","It does not approve","does not approve filters","filters, messages, sender selection","sender selection, sequence, or sending","Watch link:","campaign-builder URL","repeat the watch URL"],"approvalBoundaryRule":"Use positive Start Import copy only. Include: \"After approval, I will build the source list, add it to the campaign, and review the first 15 leads before we scale.\" Never list future non-approvals.","linkPolicy":"Do not include another watch link in Source Recommendation; describe the Start Import decision only."},{"action":"ask_source_review_choice","uses":"request_user_input","choices":["Approve scraping N recommended LinkedIn posts","Start Import for the approved source list","Revise source","Pause here"],"approvalChoiceLabelsByProvider":{"signal-discovery":"Approve scraping {scrapePostCount} recommended LinkedIn posts?","sales-nav":"Start Import for the approved Sales Nav source list","prospeo":"Start Import for the approved Prospeo source list"},"postApprovalContract":{"singleUseApproval":true,"doNotRepeatAfterApproval":["Source Recommendation","show_source_decision_card","ask_source_review_choice"],"requiredNextActionAfterApproval":"ack once; call import_leads immediately","signalDiscoveryNextTool":"import_leads({ provider: \"signal-discovery\", targetEngagerCount, maxPostsToScrape, confirmed: true })"},"autoSelectIf":"yolo_mode and projected usable pool clears the source quality floor","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]}],"requiredCampaignState":["campaignId","campaignBrief","providerSearchAssociation"],"allowedTools":["AskUserQuestion","request_user_input","update_campaign"],"doNotAllow":["create_campaign","list_senders","save_rubrics","import_leads","confirm_lead_list","queue_cells","start_campaign"],"waitFor":["lead_review_confirmed","revise_leads","confirm_with_user","auto_continue"],"transitions":{"lead_review_confirmed":"auto-execute-leads","revise_leads":"find-leads","confirm_with_user":"auto-execute-leads","auto_continue":"auto-execute-leads"}},{"id":"auto-execute-leads","label":"Materialize confirmed source list","currentStepValue":"auto-execute-leads","reference":"references/step-13-import-leads.md","onEnter":[{"tool":"get_subskill_prompt","requiredValues":{"subskillName":"create-campaign-v2-tail"}},{"tool":"import_leads","requiredFields":["campaignOfferId","selected source/list","sourceListTarget or targetEngagerCount"],"requiredValues":{"salesNavProspeoDefaultSourceListTarget":1000,"signalDiscoveryDefaultEngagerTarget":1500},"modeAddHandshake":{"firstCallReturns":"needsModeSelection when adding to an existing campaign-attached list","requiredFollowup":"retry with mode=add after explicit user/source-state compatibility is confirmed"},"surfaceDedupRatio":true},{"tool":"wait_for_lead_list_ready","repeatUntil":"ready_true_or_cancelled_or_import_failed","requiredValues":{"requireComplete":true},"onImportStillRunning":"re-run wait_for_lead_list_ready; do not call confirm_lead_list just because rows exist","partialOverrideRule":"Only if the user explicitly asks to keep going early may the next confirm_lead_list call pass allowPartialSourceList: true."},{"tool":"confirm_lead_list","requiredFields":["campaignOfferId","selectedLeadListId","reviewBatchLimit"],"requiredValues":{"reviewBatchLimit":15},"capture":["workflowTableId","reviewBatchRowIds"],"requiredPrecondition":"wait_for_lead_list_ready returned ready:true, unless the user explicitly asked to keep going early with a partial list","partialOverrideField":"allowPartialSourceList:true only after explicit user early-continue instruction","mustNotRunWhen":["wait_for_lead_list_ready reason=import_still_running and no explicit early-continue instruction","wait_for_lead_list_ready reason=cancelled","wait_for_lead_list_ready reason=import_failed","missing import job metadata"]},{"tool":"wait_for_campaign_table_ready"},{"tool":"get_rows_minimal","requiredValues":{"tableId":"{workflowTableId}","limit":15},"capture":["reviewBatchRowHash"]},{"action":"summarize_review_batch_and_advance_to_filter_choice","maxCustomerCopyLines":4,"copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"linkPolicy":"Ask add filters vs skip filters without repeating the watch link.","purpose":"ask filter choice immediately"}],"requiredCampaignState":["campaignId","providerSearchAssociation","selectedLeadListId"],"allowedTools":["get_subskill_prompt","import_leads","wait_for_lead_list_ready","confirm_lead_list","wait_for_campaign_table_ready","get_rows_minimal","update_campaign","AskUserQuestion","request_user_input"],"doNotAllow":["get_post_find_leads_scout_registry","Task","spawn_agent","list_senders","queue_cells","start_campaign","enrich_with_prospeo","bulk_enrich_with_prospeo","save_rubrics"],"waitFor":"source_list_confirmed_and_review_sample_ready","transitions":{"source_list_confirmed_and_review_sample_ready":"filter-choice","escalation_triggered":"escalation"},"hardRules":["import_leads_then_repeated_wait_for_lead_list_ready_then_confirm_lead_list_then_wait_for_campaign_table_ready","partial_source_rows_do_not_unblock_confirm_lead_list_without_explicit_user_early_continue","cancelled_or_failed_source_import_stops_before_campaign_table_copy"]},{"id":"filter-choice","label":"Filter choice","currentStepValue":"filter-choice","onEnter":[{"tool":"update_campaign","requiredValues":{"currentStep":"filter-choice","watchNarration.stage":"fit-message"}},{"action":"ask_filter_choice","uses":"request_user_input","choices":["Use filters","Skip filters","Revise source"],"autoSelectIf":"yolo_mode; choose filters unless source is tightly curated or user directed otherwise","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"copyMustInclude":["source rows are in the campaign","add fit filters before message drafting or skip filters"]}],"hardRules":["ask_filter_choice_immediately_after_review_batch_import","do_not_call_get_subskill_prompt_before_filter_choice","do_not_call_get_subskill_asset_before_filter_choice","do_not_call_get_post_find_leads_scout_registry_before_filter_choice","do_not_spawn_prospect_setup_before_filter_choice"],"requiredCampaignState":["campaignId","campaignBrief","selectedLeadListId","workflowTableId"],"allowedTools":["AskUserQuestion","request_user_input","update_campaign","get_campaign_navigation_state"],"doNotAllow":["get_subskill_prompt","get_subskill_asset","get_post_find_leads_scout_registry","Task","spawn_agent","create_campaign","list_senders","import_leads","confirm_lead_list","queue_cells","start_campaign","generate_messages"],"waitFor":["filters_enabled","filters_skipped","revise_leads"],"transitions":{"filters_enabled":"prospect-setup","filters_skipped":"message-generation","revise_leads":"find-leads"}},{"id":"prospect-setup","label":"Filter setup + message drafting","onEnter":[{"action":"persist_add_filters_approval","tool":"update_campaign","when":"filters_enabled","requiredFields":["campaignId","enableICPFilters","currentStep","watchNarration"],"requiredValues":{"enableICPFilters":true,"currentStep":"create-icp-rubric","watchNarration.stage":"fit-message","watchNarration.headline":"Create filter rules","watchNarration.visibleState":"Filter Rules is visible while Codex drafts and saves filters in the parent thread.","watchNarration.nextAction":"Review saved filter rules"},"mustRunBefore":["get_post_find_leads_scout_registry","launch_message_drafting_after_filter_choice","load_filter_reference_in_parent","save_rubrics","ask_filter_rubric_review_choice"]},{"tool":"get_post_find_leads_scout_registry","returns":["post-find-leads-message-scout"],"rule":"normal post-import registry exposes only Message Drafting; filters are parent-thread MCP work"},{"action":"launch_message_drafting_after_filter_choice","mode":"background_agent_when_host_supports_subagents","target":"post-find-leads-message-scout","when":"filters_enabled or filters_skipped after filter-choice answer","doesNotQueueCells":true,"customerNarration":"Message Drafting is preparing while Codex handles filters in the parent thread.","inputs":["campaignId","workflowTableId","brief summary: offer, buyer, source context, safe proof, blocked claims","source summary and source-use rule","3-5 sample workflow-table rows with rowId/name/title/company/signal","optional campaignName, selectedLeadListId, filterChoice"],"forbiddenSiblings":["source-scout-*","any filter background worker"],"handoffCompression":"lean_message_drafting_handoff_no_hashes_no_counts_no_full_row_data"},{"tool":"get_subskill_asset","action":"load_filter_reference_in_parent","when":"filters_enabled","requiredValues":{"subskillName":"create-campaign-v2","assetPath":"references/filter-leads.md"},"rule":"Parent thread uses this reference to draft production rubrics; do not spawn a filter worker."},{"tool":"save_rubrics","when":"filters_enabled","requiredFields":["campaignOfferId","leadScoringRubrics"],"writesCampaignState":"leadScoringRubrics","requiredSideEffects":{"enableICPFilters":true,"currentStep":"create-icp-rubric","watchNarration.headline":"Filter rules saved for review"}},{"action":"ask_filter_rubric_review_choice","uses":"request_user_input","choices":["Approve filters","Revise filters","Pause"],"copyMustInclude":["Filter rules saved for review","These rules prevent wasted sends before I score/import the list.","Recommended because of the researched ICP, source sample, and repeated false-positive patterns.","one pass example and one block example when available","approval is for the saved filter rules","Approve these filter rules."],"autoSelectIf":"yolo_mode and parent saved production-shaped rubrics","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"requiredPrecondition":"save_rubrics succeeded or active campaign rubrics verified"}],"requiredCampaignState":["campaignId","campaignBrief","selectedLeadListId","workflowTableId"],"allowedTools":["get_post_find_leads_scout_registry","get_subskill_asset","save_rubrics","get_campaign","get_rows_minimal","update_campaign","get_campaign_navigation_state","AskUserQuestion","request_user_input","Task","spawn_agent"],"doNotAllow":["create_campaign","list_senders","import_leads","confirm_lead_list","queue_cells","start_campaign","check_rubric","generate_messages"],"waitFor":["filter_rubrics_approved","revise_leads","revise_rubric","revise_messaging"],"hardRules":["after_save_rubrics_currentStep_must_stay_create-icp-rubric_until_filter_approval","filter_approval_required_before_apply-icp-rubric_or_queue_campaign_cells","do_not_move_browser_to_messages_until_filter_leads_step_is_current_or_filters_are_explicitly_skipped","no_prospect_setup_worker_or_deep_prompt_before_filter_choice","message_drafting_after_filter_choice","message_drafting_no_cells","only_message_drafting_may_spawn_background_agent","filters_are_parent_thread_mcp_work","no_post_find_leads_filter_scout_in_normal_path"],"transitions":{"filter_rubrics_approved":"message-generation","revise_leads":"find-leads","revise_rubric":"filter-rubric","revise_messaging":"message-generation","confirm_with_user":"message-review"}},{"id":"filter-rubric","label":"Rubric revision","onEnter":[{"tool":"get_subskill_asset","requiredValues":{"subskillName":"create-campaign-v2","assetPath":"references/filter-leads.md"}},{"tool":"save_rubrics","requiredFields":["campaignOfferId","leadScoringRubrics"],"writesCampaignState":"leadScoringRubrics","requiredSideEffects":{"enableICPFilters":true,"currentStep":"create-icp-rubric","watchNarration.headline":"Filter rules saved for review"}},{"action":"ask_filter_rubric_review_choice","uses":"request_user_input","choices":["Approve filters","Revise filters","Pause"],"copyMustInclude":["These rules prevent wasted sends before I score/import the list.","approval object is filter rules only","approval is for the filter rules","Approve these filter rules."],"autoSelectIf":"yolo_mode and rubrics are production-shaped","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]}],"requiredCampaignState":["campaignId","workflowTableId"],"allowedTools":["get_subskill_asset","save_rubrics","AskUserQuestion","request_user_input"],"doNotAllow":["create_campaign","list_senders","import_leads","confirm_lead_list","update_campaign","queue_cells","start_campaign","check_rubric"],"waitFor":["filter_rubrics_approved","revise_leads","confirm_with_user","auto_continue"],"transitions":{"filter_rubrics_approved":"message-generation","revise_leads":"find-leads","confirm_with_user":"message-generation","auto_continue":"message-generation"}},{"id":"message-generation","label":"Message drafting","onEnter":[{"action":"set_message_review_visible_step_by_filter_choice","tool":"update_campaign","branchRules":["yes after filter approval: currentStep=apply-icp-rubric; wait on Filter Leads","no: currentStep=messages; message review"],"watchNarration.stage":"fit-message"},{"action":"join_or_recover_message_drafting","target":"post-find-leads-message-scout","toolCallRequiredBeforeDraft":["join already-running Message Drafting when prospect-setup launched it","run Message Drafting via post-find-leads-message-scout only if missing; yolo counts","handoff lean basis only: campaignId, workflowTableId, brief summary, source summary/source-use rule, 3-5 sample workflow-table rows","do not paste copied row counts, brief hashes, review-batch hashes, full reviewBatchRowIds, broad row data, or local debug artifacts into the spawn prompt","branch loads current brief/context and sample rows, full generate-messages prompt, and all referenced assets","before return branch loads create-campaign-v2-validation prompt and runs internal validation","return only templateRecommendation, tokenFillRules, renderedGoodSample, status, approveOrReviseRecommendation, validationStatus, outputAt/outputHash, and blocked/retry detail","do not return renderedFallbackSample, concerns, or qaReceipt on the normal happy path","if no yolo and permission missing, ask once before parent inline fallback","use generic gpt-5.5 xhigh Message Drafting agent if named unavailable"],"stateSource":"message branch-loaded live campaign/table state plus parent-provided sample rows","outputState":"messageDraftRecommendation with internal validation passed","revisionMode":{"when":"revise_messaging, message QA request, or latest user message requests template changes before approve-message","route":"send feedback/QA/rewrite request to post-find-leads-message-scout or generic gpt-5.5 xhigh Message Drafting branch","requiredInputs":["latest user feedback","current messageDraftRecommendation and basisToken/outputHash","lean campaign/table basis and brief summary; branch reloads live state"],"forbiddenParentActions":["rewrite template in parent","QA template in parent from memory","update_campaign_brief before approve-message"],"output":"revised messageDraftRecommendation rendered before request_user_input"},"onlyMessageBackgroundAgent":true,"forbiddenSiblingAgents":["source-scout-*","any filter background worker"],"handoffCompression":"lean_message_drafting_handoff_no_hashes_no_counts_no_full_row_data"}],"requiredCampaignState":["campaignId","campaignBrief","selectedLeadListId","workflowTableId"],"allowedTools":["get_subskill_prompt","get_campaign","get_rows_minimal","update_campaign","Task","spawn_agent"],"toolRules":["message_drafting_agent_first_no_silent_parent_fallback; yolo counts","on_filters_enabled_path_parent_must_not_enter_message_review_until_save_rubrics_success_and_filter_approval","brief.md, lead-review.md, and lead-sample.json are optional debug context only.","messageDraftRecommendation returns templateRecommendation, tokenFillRules, renderedGoodSample, status, approveOrReviseRecommendation, validationStatus, outputAt, outputHash, and error/retry detail.","messageDraftRecommendation does not return renderedFallbackSample, concerns, or qaReceipt on the normal happy path.","If campaign/table/sample basis does not match, classify the output stale or blocked.","message_revision_feedback_routes_to_message_drafting_agent_not_parent","message_qa_routes_to_message_drafting_agent_not_parent","message_drafting_loads_full_generate_messages_prompt_all_chunks","message_drafting_loads_all_reference_assets_via_get_subskill_asset","message_drafting_loads_create_campaign_v2_validation_prompt_before_return","message_drafting_handoff_uses_lean_basis_no_hashes_no_counts_no_full_row_id_list","message_drafting_loads_current_campaign_brief_before_drafting","parent_may_load_generate_messages_only_for_explicitly_approved_inline_fallback"],"doNotAllow":["create_campaign","list_senders","save_rubrics","import_leads","confirm_lead_list","queue_cells","start_campaign","generate_messages","AskUserQuestion","request_user_input"],"waitFor":["message_validation_ready","revise_rubric","revise_messaging"],"transitions":{"message_validation_ready":"message-review","revise_rubric":"filter-rubric","revise_messaging":"message-generation"},"revisionLoop":{"trigger":"user gives copy feedback, asks for QA/update, or chooses revise-messaging","required":["route latest user feedback or QA request to Message Drafting with current recommendation and live campaign/table state","produce a new messageDraftRecommendation with revisionNotes or validationStatus","render revised ## Message Template, ## Rendered Example, and What changed before asking approval"],"blocked":["asking whether an unseen new version is better","reusing the old template after acknowledging feedback","rewriting the template in the parent thread","update_campaign_brief before approve-message","request_user_input or AskUserQuestion during message-generation","QAing the template in the parent thread"],"outputState":"messageDraftRecommendation"},"hardRules":["message_revision_must_render_new_template_before_approval_question","message_revision_saves_only_after_approve_message","message_generation_must_not_call_request_user_input","message_generation_must_transition_to_message_review_only_after_renderable_draft_state","message_drafting_agent_first_no_silent_parent_fallback","message_revision_routes_to_message_drafting_agent","message_qa_routes_to_message_drafting_agent","filter_path_requires_saved_filters_before_message_review","only_message_drafting_may_spawn_background_agent"]},{"id":"message-review","label":"Message review","onEnter":[{"action":"render_message_review_from_state","requiredState":["campaignBrief","selectedLeadListId","workflowTableId","messageDraftRecommendation"],"requiredVisibleLabels":["## Message Template","## Rendered Example","Good token fill:","My take:","Question: approve-message or revise-messaging?","Recommendation:"],"doNotShowByDefault":["Rendered fallback sample","Concerns","QA receipt","Token Notes","Good omit / fallback","Bad fill to avoid","Token Adherence Table"],"internalPersistenceOnly":["Token Fill Rules","Token Fill Examples","fallback guidance","bad-fill avoidance notes","validation notes","QA details"],"copyMustInclude":["one recommended template","one rendered sample","token rules and fallbacks","full list remains paused"],"copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"revisionRenderRule":"After revise_messaging, a message QA request, or user copy feedback, route feedback to Message Drafting and show revised template, rendered example, and What changed before ask_message_review_choice; never ask if an unseen version is better.","parentMustNot":["rewrite template from memory","invent validation summary without Message Drafting output","render qaReceipt, concerns, or renderedFallbackSample on the normal happy path"]},{"action":"ask_message_review_choice","uses":"request_user_input","choices":["approve-message","revise-messaging"],"copyMustInclude":["approve this message template and continue","nothing sends from this approval"],"autoSelectIf":"yolo_mode and Recommendation is approve-message; revise autonomously when Recommendation is revise-messaging","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"requiredPrecondition":"current or revised template and rendered example are visible in this turn","revisionPrecondition":"after revise_messaging, revised template is visible before this question"},{"action":"sync_approved_message_set_to_campaign_brief","tool":"update_campaign_brief","when":"after approve-message","requiredFields":["campaignId","approvedMessageTemplate","Token Fill Rules","Token Fill Examples"],"writesCampaignState":"approvedMessageTemplate","revisionApprovalRule":"If the user requested revisions, write only the latest Message Drafting-approved revised template and token rules after approve-message.","forbiddenBefore":"approve-message"}],"requiredCampaignState":["campaignId","workflowTableId","messageDraftRecommendation"],"allowedTools":["AskUserQuestion","request_user_input","update_campaign_brief","update_campaign","get_rows_minimal"],"doNotAllow":["create_campaign","list_senders","save_rubrics","import_leads","confirm_lead_list","start_campaign"],"waitFor":["message_approved","revise_messaging"],"transitions":{"message_approved":"validate-sample","revise_messaging":"message-generation"}},{"id":"validate-sample","label":"Validate campaign-table execution slice","currentStepValue":"apply-icp-rubric","reference":"references/sample-validation-loop.md","visibleStepRule":"Filter Leads is reached only after saved-filter approval; on approve-message, save the template and queue bounded Enrich Prospect cells through selector-based campaign processing.","onEnter":[{"tool":"update_campaign","requiredValues":{"currentStep":"apply-icp-rubric","watchNarration.stage":"fit-message"},"watchNarrationRule":"Say the template is saved and Filter Leads is now running the bounded enrichment and scoring pass."},{"tool":"queue_campaign_cells","requiredFields":["workflowTableId","columnRole","rowSelector"],"requiredValues":{"columnRole":"enrich","rowSelector":{"type":"reviewBatch"},"forceRerun":false},"targetCountSource":"WorkflowTable.config.mcp.reviewBatch.rowCount (default 15)"},{"tool":"wait_for_campaign_processing","requiredFields":["workflowTableId","minPassedCount"],"requiredValues":{"minPassedCount":1},"readVia":"stats_only_tool_result","timeoutGuidance":"If this times out, do not repoll identical args; use partial diagnostics to revise filters or surface blocked sample state.","customerSummaryPattern":["{checked} leads checked","{passed} passed fit scoring","{blocked} blocked before sending","full list remains paused until approval"]},{"action":"handle_partial_or_timeout_sample","customerStatus":"sample-needs-revision","rule":"Do not repeat waits indefinitely; surface partial status and route to revision.","copyMustInclude":"completed, passed, pending, blocked before sending, and full list remains paused"}],"requiredCampaignState":["campaignId","workflowTableId","approvedMessageTemplate","filterRubricsApproved when enableICPFilters=true"],"allowedTools":["get_subskill_asset","queue_campaign_cells","select_campaign_cells","get_campaign_table_schema","wait_for_campaign_processing","update_campaign","AskUserQuestion","request_user_input"],"doNotAllow":["import_leads","list_senders","start_campaign","enrich_with_prospeo","bulk_enrich_with_prospeo","check_rubric"],"hardRules":["campaign_processing_waits_are_stats_only_by_default","queue_review_batch_by_selector_never_fetch_rows_for_cell_ids","timeout_never_repeats_without_customer_handoff","timeout_or_underfloor_sample_never_advances_to_settings"],"waitFor":["sample_validated","sample_revision_required"],"transitions":{"sample_validated":"auto-execute-messaging","sample_revision_required":"lead-review","revise_leads":"find-leads","revise_rubric":"filter-rubric","escalation_triggered":"escalation"}},{"id":"auto-execute-messaging","label":"Generate initial campaign-row messages","currentStepValue":"auto-execute-messaging","references":["references/parallel-critique-protocol.md","references/thomas-variant-selection.md","references/thomas-revision-filters.md","references/step-15-re-cascade.md"],"onEnter":[{"tool":"queue_campaign_cells","batchSize":100,"when":"any passing row has pending, empty, or stale Generate Message cell","requiredFields":["workflowTableId","columnRole","rowSelector"],"requiredValues":{"columnRole":"generateMessage","rowSelector":{"type":"needsGeneratedMessage"},"forceRerun":false},"cellSource":"selector-engine needsGeneratedMessage rows using approved campaign brief template"},{"tool":"wait_for_campaign_processing","purpose":"wait_for_first_current_revision_generated_message","requiredValues":{"minGeneratedMessages":1,"templateRevision":"current"},"readVia":"stats_only_tool_result","invariant":"A generated message implies the pass gate; stale or wrong-revision messages are excluded from readiness."},{"action":"observe_generate_message_results","reference":"references/step-15-re-cascade.md"},{"action":"enforce_token_contract","modeFromConfig":"messaging.tokenContract"},{"action":"optional_critique_pass","enabledFromConfig":"messaging.critique.enabled","plan":"85-03","protocol":"references/parallel-critique-protocol.md","sampleSizeFromConfig":"messaging.critique.sampleSize","budgetUsdCapFromConfig":"messaging.critique.budgetUsdCap","perCriticTimeoutFromConfig":"messaging.critique.perCriticTimeoutSeconds","totalTimeoutFromConfig":"messaging.critique.totalTimeoutSeconds","criticsFromConfig":"messaging.critique.critics","enforceFinalizerPassFromConfig":"messaging.critique.synthesis.enforceFinalizerPass","rejectOnFakeProofFromConfig":"messaging.critique.rejectOnFakeProof","rejectOnUnsupportedTokenFromConfig":"messaging.critique.rejectOnUnsupportedToken","onBudgetTrip":"halt_critique_continue_plain_tail","onPerCriticTimeout":"drop_critic_proceed_with_remaining","onTotalTimeout":"persist_plain_message_for_row","onTokenContractViolation":"persist_plain_message_for_row","onFakeProof":"persist_plain_message_for_row"},{"action":"optional_opus_subset","enabledFromConfig":"messaging.critique.opus.enabled","selection":"references/thomas-variant-selection.md","maxMessagesPerPassFromConfig":"messaging.critique.opus.maxMessagesPerPass","budgetUsdCapFromConfig":"messaging.critique.opus.budgetUsdCap","onOpusBudgetTrip":"halt_opus_continue_non_opus","onOpusTokenContractViolation":"fallback_to_non_opus_rewrite"},{"tool":"update_campaign","requiredValues":{"currentStep":"auto-execute-messaging","watchNarration.stage":"review-ready"},"watchNarrationRule":"Say the first passing generated message is ready in Messages; next is review before Settings."},{"action":"ask_generated_message_review_choice","uses":"request_user_input","choices":["Approve reviewed draft rows and continue to Settings","Revise filters","Revise message template","Pause here"],"copyMustInclude":["approve the reviewed draft rows and continue to Settings","tokens resolved","company/person match","proof claim","prospect angle","language/tone when known","obvious bad fits","Would I take this call?","weak personalization can burn the sender's reputation","full list remains paused","nothing sends from this approval"],"autoSelectIf":"yolo_mode and the first passing generated message clears the quality floor","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]}],"allowedTools":["get_subskill_asset","get_campaign_table_schema","select_campaign_cells","queue_campaign_cells","wait_for_campaign_processing","revise_message_template_and_rerun","update_campaign","AskUserQuestion","request_user_input"],"doNotAllow":["import_leads","list_senders","start_campaign","generate_messages"],"hardRules":["generated_message_count_excludes_stale_or_wrong_revision_messages","message_template_revision_uses_brief_update_then_generate_message_rerun","do_not_overwrite_generated_message_cells_directly","critique_failure_never_escalates","critique_sample_size_bounded_by_config","first_passing_generated_message_unblocks_review","critics_fixed_at_targeting_copy_voice","synthesis_enforces_phase_84_token_contract","opus_reserved_for_highest_value_subset","proposed_token_never_persisted_in_rewrite"],"waitFor":["generated_messages_approved","sample_revision_required"],"transitions":{"generated_messages_approved":"awaiting-user-greenlight","revise_filters":"filter-rubric","revise_messaging":"message-generation","escalation_triggered":"escalation"}},{"id":"awaiting-user-greenlight","label":"Settings, sender, sequence, and greenlight","currentStepValue":"awaiting-user-greenlight","reference":"references/final-handoff-contract.md","onEnter":[{"tool":"get_campaign"},{"tool":"list_senders","purpose":"surface available connected senders only at Settings"},{"tool":"update_campaign","requiredValues":{"currentStep":"settings","watchNarration.stage":"review-ready"},"watchNarrationRule":"Say message review is complete and the app is on Settings for sender choice. Mention lead research/filtering already happened outside the user's LinkedIn account and nothing sends until Start."},{"action":"surface_sender_and_slack_handoff","requiredVisibleContent":["connect or select a LinkedIn sender","Lead research and filtering already happened outside your LinkedIn account.","This account is only used for approved sending after final launch.","Nothing sends until the final Start step.","Slack reply review","recommended sequence","final launch confirmation is still ahead"],"copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]},{"action":"ask_sender_selection","uses":"request_user_input","singleChoice":true,"choices":["Use this connected sender","Connect a different sender in Settings","Pause here"],"autoSelectIf":"yolo_mode and exactly one safe connected sender is available","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]},{"action":"attach_selected_sender","tool":"update_campaign","when":"user selected an available connected sender","requiredValues":{"senderIds":["{selectedSenderId}"],"currentStep":"sequence","watchNarration.stage":"review-ready"},"watchNarrationRule":"Say the sender was attached and the app is moving to Sequence review; sequence remains editable and nothing sends until Start."},{"tool":"attach_recommended_sequence","when":"after senderIds are attached","requiredValues":{"campaignId":"{campaignId}","currentStep":"send","watchNarration.stage":"review-ready"},"watchNarrationRule":"The sequence tool owns this visible beat: say the recommended follow-up sequence is attached, the app is on final launch review, and it is still not sending until Start."},{"action":"ask_final_launch_greenlight","uses":"request_user_input","singleChoice":true,"choices":["Start campaign","Review campaign first","Pause here"],"copyMustInclude":["quality confidence means sample messages and prospect angle were checked","launch confidence means sender, sequence, and Start are ready","approved messages begin sending according to the sequence","replies and meetings follow connected settings","you can monitor and pause","no hidden extra approval disappears after clicking Start"],"onUserStart":"claude-greenlight","neverAutoSelectInYolo":true,"copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]}],"allowedTools":["get_campaign","get_campaign_navigation_state","list_senders","update_campaign","attach_recommended_sequence","AskUserQuestion","request_user_input"],"doNotAllow":["start_campaign","import_leads"],"autoStart":false,"watchRequired":true,"waitFor":["sender_connection_required","sender_attached","sequence_attached","ready_to_launch","user_greenlight","ui_start_detected"],"transitions":{"sender_connection_required":"awaiting-user-greenlight","sender_attached":"awaiting-user-greenlight","sequence_attached":"awaiting-user-greenlight","ready_to_launch":"awaiting-user-greenlight","user_greenlight":"claude-greenlight","ui_start_detected":"running"}},{"id":"claude-greenlight","label":"Explicit launch","reference":"references/final-handoff-contract.md","onEnter":[{"tool":"get_campaign"},{"action":"verify_sequence_and_current_step_before_start","requiredState":["workflowTableId","senderIds","sequenceTemplate","at least one approved generated message","currentStep in awaiting-user-greenlight|claude-greenlight|send"]},{"tool":"start_campaign","requiredFields":["campaignId"],"persistsCurrentStep":"running","watchNarrationRule":"After start_campaign succeeds, the running state must say the final greenlight was accepted, the campaign is now live/running, and the user can watch progress from the campaign."}],"allowedTools":["get_campaign","attach_recommended_sequence","start_campaign","AskUserQuestion","request_user_input"],"watchRequired":true,"waitFor":"campaign_started","transitions":{"campaign_started":"running"}},{"id":"running","label":"Campaign is live","currentStepValue":"running","onEnter":[{"action":"surface_campaign_live_confirmation_without_watch_link","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]}],"allowedTools":["get_campaign","AskUserQuestion","request_user_input"],"doNotAllow":["start_campaign"],"terminal":true},{"id":"escalation","label":"Escalation","reference":"references/escalation-ladder.md","allowedTools":["AskUserQuestion","request_user_input"],"doNotAllow":["start_campaign","import_leads"],"transitions":{"revise_brief":"brief-interview","revise_leads":"find-leads","revise_rubric":"filter-rubric","revise_messaging":"message-generation","abort":"abort"}},{"id":"abort","label":"Abort","allowedTools":["AskUserQuestion","request_user_input"],"terminal":true}]}
1
+ {"version":"v2.1-compact","workflow":"create-campaign-v2","principle":"CampaignOffer state/watch link are canonical. Create shell, approve Find Buyers Plan and Start Import, confirm source rows, process first slice, approve filters/message, then run bounded cascade before Settings and explicit start.","normalCustomerPath":"Use campaign state, MCP responses, and concise watchNarration. Do not create, read, link, or surface local draft files. Print the exact tokenized create_campaign.watchUrl only once at the initial brief handoff.","legacyCompatibility":{"validationSubskill":"create-campaign-v2-validation","tailSubskill":"create-campaign-v2-tail","rule":"Legacy validation/rehearsal files are opt-in diagnostics only and are not active flow gates."},"commitGateChoices":["approve","revise-brief","revise-leads","revise-rubric","revise-messaging","abort"],"canonicalStateFields":["campaignId","watchUrl","campaignBrief","currentStep","watchNarration","interactionMode","providerSearchAssociation","selectedLeadListId","workflowTableId","filterChoice","leadScoringRubrics","messageDraftRecommendation","approvedMessageTemplate","senderIds","sequenceTemplate","runningState"],"watchNarrationTransitionContract":{"rule":"Every watched currentStep switch must include fresh watchNarration.","requiredFields":["stage","headline","visibleState","agentIntent","nextAction"],"copyMustInclude":["what just happened","current visible page/state","next user action"],"appliesToTools":["create_campaign","update_campaign","attach_recommended_sequence","start_campaign"],"oneTimeWatchLinkPolicy":"After the initial brief handoff, customer-facing turns must not print another watch link unless the user asks or link recovery is needed."},"lazyReferences":{"watch":["references/watch-link-handoff.md","references/watch-guide-narration.md"],"source":["references/lead-validation-preview.md","references/step-13-import-leads.md"],"filter":["references/filter-leads.md"],"message":[],"tail":["references/sample-validation-loop.md","references/step-15-re-cascade.md","references/final-handoff-contract.md"]},"safetyBoundaries":["Do not call list_senders before Settings after message approval.","Do not import leads until Start Import is approved.","Do not queue cells until confirmed source rows exist in the campaign and the message/filter gates are satisfied.","Do not call start_campaign until the user explicitly confirms launch.","Do not use local files as durable state in normal customer runs."],"yoloMode":{"triggerPhrases":["yolo","--yolo","mode=yolo","autopilot","use best guesses","use best estimates","answer for me","just run it","yolo autopilot"],"identityRequestOnlyWhenMissing":true,"operatorDirectionsRule":"Treat freeform directions supplied at invocation or later as durable operator directions; newest conflicting direction wins.","setInteractionModeAfterCampaignCreate":"autonomous","autoSelectsPreLaunchChoices":["campaign focus","brief approval","source plan","Start Import approval","filters vs skip filters","filter rubric approval","message template approval when recommendation is approve-message","generated message review when quality floor passes","sender selection when exactly one connected sender is safe"],"mustPauseFor":["missing LinkedIn profile URL or handle","missing credentials or required data","ambiguous choice with no reasonable estimate","source/message/filter quality floor failure","final live launch confirmation"],"neverAutoStart":true},"steps":[{"id":"bootstrap","label":"Bootstrap","onEnter":[{"tool":"bootstrap_create_campaign","requiredValues":{"flowVersion":"v2"}},{"tool":"get_subskill_prompt","requiredValues":{"subskillName":"create-campaign-v2"}}],"allowedTools":["bootstrap_create_campaign","get_auth_status","get_active_workspace","get_subskill_prompt","AskUserQuestion","request_user_input"],"doNotAllow":["create_campaign","list_senders","save_rubrics","import_leads","confirm_lead_list","update_campaign","queue_cells","start_campaign"],"waitFor":"bootstrap_complete","transitions":{"bootstrap_complete":"brief-interview"}},{"id":"brief-interview","label":"Client, offer, research, and brief","onEnter":[{"action":"resolve_campaign_identity_before_strategy_packet","allowedTools":["fetch_company","fetch_linkedin_profile","WebFetch","WebSearch"],"mustNotInferFromNameOnly":true,"doNotPresentSenderPickerBeforeIdentityInference":true,"fallback":"Ask only: \"What is your LinkedIn profile URL or handle?\" Normalize bare handles or `/in/...` paths to `https://www.linkedin.com/in/{handle}/`. If the input is not a profile, ask again for the person profile URL before strategy questions.","requiresLinkedInProfileUrl":true,"doNotAcceptAsIdentityInput":["non-profile URL","company page","company/name-only input without a profile handle"],"acceptsLinkedInProfileHandle":true,"normalizeLinkedInProfileHandleToUrl":true},{"action":"run_campaign_identity_research_before_strategy_packet","target":"research-sender","requiredCompletion":"complete_sender_research","allowedTools":["get_subskill_prompt","fetch_linkedin_profile","fetch_company","fetch_linkedin_posts","fetch_company_posts","WebFetch","WebSearch","complete_sender_research"],"requiredInput":"LinkedIn profile URL or handle"},{"action":"confirm_target_before_strategy_packet","uses":"request_user_input","singleChoice":true,"question":"Who should we target first?","options":["Use Sellable's researched recommendation","Choose a different buyer","I'm not sure yet"],"copyMustInclude":["research basis","recommendation is editable","who to target"],"requiredOption":"Other / custom","neverCollectOpenTextWithStructuredQuestion":true,"skipIf":"user already supplied a clear target or yolo_mode with any reasonable best-estimate target"},{"action":"confirm_current_offer_before_strategy_packet","uses":"request_user_input","question":"What should we pitch to prospects first?","options":["Use Sellable's researched recommendation","Use my current pitch","Shape the pitch together"],"copyMustInclude":["research basis","public LinkedIn research may be stale","recommendation is editable","pitch to prospects"],"skipIf":"user already supplied a clear current offer or yolo_mode with any reasonable researched recommendation"},{"action":"confirm_trust_proof_before_strategy_packet","uses":"request_user_input","singleChoice":true,"question":"What is the strongest credibility signal we can lead with?","options":["Use Sellable's recommended proof","Use customer proof or a case study","Use founder or company credibility"],"copyMustInclude":["build trust with prospects","recommendation is editable","proof to use or avoid"],"requiredOption":"Other / custom","skipIf":"user already supplied clear proof to use or avoid, or yolo_mode with any reasonable researched proof"},{"action":"choose_prospect_source_path_before_strategy_packet","uses":"request_user_input","singleChoice":true,"question":"How should we find prospects?","options":["Find prospects for me","Use a CSV of LinkedIn profiles","Use a CSV of company domains"],"copyMustInclude":["prospects","no one added yet","find prospects for me"],"skipIf":"user already supplied a source path or yolo_mode with any reasonable source path"},{"action":"infer_strategy_packet_in_yolo_mode","when":"yolo_mode","skipStructuredSetupQuestions":true,"inferFields":["buyer segment","offer/CTA","proof to use or avoid","lead source","filter choice","message direction"],"sourceOfTruth":"identity/company lookup plus operator directions","mustStateAssumptionsInBrief":true},{"action":"render_supplied_setup_receipt_before_brief_when_setup_questions_skip","when":"any setup question is skipped because the user already supplied or yolo mode inferred identity, target, offer, proof, or source","output":"normal chat receipt before the campaign brief or watch-link handoff","copyMustInclude":["Accepted LinkedIn input: normalized to the required LinkedIn profile URL.","Offer path: supplied current offer or Sellable's researched recommendation; you can replace it with your current offer."],"copyMustNotInclude":["Campaign Identity"]},{"action":"create_watchable_campaign_shell_with_v1_brief","tool":"create_campaign","requiredFields":["name","campaignBrief","clientProspectId or senderLinkedinUrl","currentStep","watchNarration"],"requiredValues":{"currentStep":"create-offer","watchNarration.stage":"brief"},"capture":["campaignId","watchUrl"],"canonicalStateWrites":["campaignId","watchUrl","campaignBrief","currentStep:create-offer"]},{"action":"surface_campaign_shell_watch_link","watchUrlSource":"create_campaign.watchUrl","requiredWatchUrlShape":"exact create_campaign.watchUrl; direct /campaign-builder/{campaignId}?mode={claude|codex} URL with workspaceId and token","copyMustInclude":["We'll keep building the campaign in this chat.","You can watch it being built in real time in the app here:","I'll ask for your approval whenever I need your expertise or taste before moving forward.","Send changes here."],"immediateNextMainChatLine":"Ask for brief approval now. After approval, say: \"Brief approved. Next, we'll choose where to find buyers. I won't add anyone yet.\"","codexBrowserHandoff":{"openWhenAvailable":false,"printWatchLinkOnly":true,"tellUserCommandEnterOrClick":false,"mustNotUseBrowserAutomation":true,"fallbackMustNotClaimInspection":true},"copyMustAvoid":["bare /campaign-builder/{campaignId} URL","derived watch URL","second Watch link:","Next, we'll choose where to find buyers"],"oneTimeOnly":true}],"allowedTools":["get_subskill_prompt","fetch_company","fetch_company_posts","fetch_linkedin_profile","fetch_linkedin_posts","complete_sender_research","create_campaign","AskUserQuestion","request_user_input"],"doNotAllow":["list_senders","save_rubrics","import_leads","confirm_lead_list","queue_cells","start_campaign"],"waitFor":["campaign_shell_created","brief_ready","confirm_with_user"],"transitions":{"campaign_shell_created":"brief-review","brief_ready":"brief-review","confirm_with_user":"brief-review"}},{"id":"brief-review","label":"Brief review","onEnter":[{"action":"render_brief_inline","minimumVisibleDetail":"campaign direction, buyer, offer, proof, source plan, safety gates","copyMustInclude":["This brief is based on Sellable's research and your answers.","If your site or LinkedIn is stale","Do you agree with this researched campaign direction?"],"copyMustNotInclude":["quoted first-message copy","Message Angle as final proof","This approval covers","does not approve adding people","does not approve scraping posts","selecting a sender","attaching a sequence","Campaign Identity","what should this campaign sell first","sell first","[from you]","[from LinkedIn]","[from website]","[from case study]","[Sellable recommendation]"],"messageHintRule":"If any message-shape hint remains, keep it as non-final bullets and say real examples come after leads are found and filtered.","approvalBoundaryRule":"Keep this gate positive and short. Do not list later steps this approval does not cover; ask approve/revise and then move to choosing where to find buyers.","sectionLabelRule":"Use ## Sender and Company for the person/company context; never render ## Campaign Identity.","skipIf":"the full brief was already rendered in the current shell-creation handoff before create_campaign returned","renderOnceRule":"The brief must be visible exactly once before approval. Do not render it again immediately after shell creation; append the one watch-link handoff and ask the approval question.","copyMustAvoid":["duplicate brief render after shell creation","second Watch link:"]},{"action":"ask_brief_choice","uses":"request_user_input","choices":["Approve brief","Revise brief","Approve + YOLO autopilot setup"],"skipIf":"yolo_mode; auto_continue after rendering assumptions unless brief quality floor fails","question":"Do you agree with this researched campaign direction?","autonomousChoice":"Approve + YOLO autopilot setup","choiceDescriptions":{"Approve + YOLO autopilot setup":"Use best guesses to finish setup and stop before final launch."}}],"requiredCampaignState":["campaignId","watchUrl","campaignBrief","currentStep"],"allowedTools":["AskUserQuestion","request_user_input","update_campaign"],"doNotAllow":["create_campaign","list_senders","import_leads","confirm_lead_list","queue_cells","start_campaign"],"waitFor":["user_brief_confirmed","revise_brief","auto_continue"],"transitions":{"user_brief_confirmed":"find-leads","revise_brief":"brief-interview","auto_continue":"find-leads"}},{"id":"find-leads","label":"Find leads","sourceSelectionFunnel":{"preScoutRecommendationGate":{"required":true,"label":"Find buyers plan approval","mustHappenBefore":["get_provider_prompt","search_signals","search_sales_nav","search_prospeo","fetch_post_engagers"],"show":["buyer groups or places we could check","best place to start","why the right buyers are likely to be there","what signs the next search will check","where to look next if the first place is too thin","what approval authorizes"],"approvalAuthorizes":"looking for the best places to find buyers; no one added yet","explanationMustInclude":["where the right buyers are already talking","why that place fits this campaign","enough likely prospects","what counts as a good sign","where to look next if thin","I won't add anyone yet","choose where to find buyers"],"yoloMode":{"autoApproveRecommendedLane":true,"mustShowAssumedChoice":true,"pauseIfConfidenceLow":true},"customerLanguage":{"readability":"grade-5","requiredHeading":"Find Buyers Plan","prefer":["place to look","best place to start","people to check","prospects","I won't add anyone yet"],"avoid":["lane","source scouting","provider","precision/scale tradeoff","evidence quality","pilot volume","ICP","workflow pain","lead-source scouting","not importing leads"],"termRule":{"buyers":"target market","peopleToCheck":"raw reactions/comments before fit is known","prospects":"likely usable people after fit","leads":"campaign rows"}},"questionOrder":"update_campaign to pick-provider, render ## Find Buyers Plan in normal chat without repeating the watch link, then open the structured approval question; never ask first or show the plan after approval","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"approvalFreshnessRule":"Only an approval question opened after the visible Find Buyers Plan, or an explicit source choice made after that plan, can set source_lane_approved. Do not reuse brief approval or pre-plan provider state."},"defaultWhenSourceUnspecified":["signal-discovery","sales-nav-recent-active","sales-nav-general","prospeo"],"parallelAllowedOnlyWhen":["user explicitly requested source comparison"]},"onEnter":[{"tool":"update_campaign","requiredValues":{"currentStep":"pick-provider","watchNarration.stage":"find-leads","watchNarration.headline":"Review where to find buyers","watchNarration.visibleState":"The app is showing source selection before lead finding starts.","watchNarration.agentIntent":"Codex is explaining where it recommends looking first and where it will look next if that is too thin.","watchNarration.nextAction":"Approve where to look first or choose another place","watchNarration.safety":"Only deciding where to look. No one is added yet."}},{"action":"render_find_buyers_plan_inline","oneShot":true,"requiredPrecondition":"currentStep=pick-provider has been saved with update_campaign","mustHappenAfter":["update_campaign currentStep=pick-provider"],"mustHappenBefore":["ask_find_buyers_plan_choice","get_provider_prompt","search_signals","search_sales_nav","search_prospeo","fetch_post_engagers"],"output":"normal chat text before any request_user_input approval panel","requiredHeading":"Find Buyers Plan","requiredInlineFields":["plain-language buyer groups or places for this campaign","best place to start","why the right buyers are likely to be there","what signs the next search will check","where to look next if the first place is too thin","what approval authorizes"],"copyMustInclude":["Find Buyers Plan","best place to start","I won't add anyone","choose where to find buyers","I won't add anyone yet"],"copyMustAvoid":["lane","source scouting","provider","precision/scale tradeoff","evidence quality","pilot volume","ICP","workflow pain","lead-source scouting","not importing leads","Watch link:","campaign-builder URL","repeat the watch URL"],"approvalBoundary":"Explain what approval authorizes before asking: looking for the best places to find buyers; no one is added yet.","linkPolicy":"Do not include another watch link. The first brief handoff already gave the user the live app URL."},{"action":"ask_find_buyers_plan_choice","uses":"request_user_input","oneShot":true,"requiredPrecondition":"render_find_buyers_plan_inline completed in normal chat after pick-provider state was saved; no earlier approval can satisfy this","skipIf":"source_lane_approved was set by ask_find_buyers_plan_choice after the visible Find Buyers Plan, leadSourceProvider was explicitly chosen by the user after that plan, or yolo_mode auto-selected source_lane_approved after showing the assumed choice","choices":["Start with LinkedIn posts","Start with active LinkedIn profiles","Start with company/contact search","Choose a different place","Pause here"],"approvalChoiceLabelsByProvider":{"signal-discovery":"Start with LinkedIn posts","sales-nav":"Start with active LinkedIn profiles","prospeo":"Start with company/contact search"},"approvalState":"source_lane_approved","copyMustInclude":["Approve this plan for where to find buyers?","Start with LinkedIn posts"],"mustNotHappenBefore":["render_find_buyers_plan_inline"],"approvalStateRule":"Set source_lane_approved here after the visible plan; never from brief approval, generic approval, pre-plan provider state, or artifacts."},{"action":"persist_provider_search_step_before_search","tool":"update_campaign","requiredPrecondition":"source_lane_approved set after the visible Find Buyers Plan approval question","providerCurrentStepMap":{"signal-discovery":"signal-discovery","sales-nav":"sales-nav","prospeo":"prospeo"},"requiredValues":{"leadSourceType":"new","leadSourceProvider":"approved provider","currentStep":"provider-specific current step","watchNarration.stage":"find-leads","watchNarration.headline":"Searching the approved place","watchNarration.safety":"Looking only. No one is added yet."},"mustRunBefore":["search_signals","search_sales_nav","search_prospeo","fetch_post_engagers"]},{"action":"run_parent_thread_source_funnel","requiredPrecondition":"source_lane_approved after visible Find Buyers Plan approval","mode":"parent_thread_inline_sequential","sourceAgents":"forbidden in normal create-campaign","loadsOnlyActiveProviderPrompt":true,"defaultOrder":["signal-discovery","sales-nav-recent-active","sales-nav-general","prospeo"],"stopOnFirstViableUnlessComparisonRequested":true}],"requiredCampaignState":["campaignId","campaignBrief","currentStep"],"allowedTools":["get_provider_prompt","lookup_sales_nav_filter","search_sales_nav","search_prospeo","search_signals","select_promising_posts","fetch_post_engagers","fetch_company","fetch_linkedin_profile","load_csv_linkedin_leads","load_csv_domains","get_rows_minimal","update_campaign","AskUserQuestion","request_user_input","get_campaign_navigation_state"],"doNotAllow":["create_campaign","list_senders","save_rubrics","import_leads","confirm_lead_list","queue_cells","start_campaign","Task","spawn_agent"],"waitFor":["lead_review_ready","revise_brief","confirm_with_user"],"transitions":{"lead_review_ready":"lead-review","revise_brief":"brief-interview","confirm_with_user":"lead-review"}},{"id":"lead-review","label":"Start Import approval","onEnter":[{"action":"show_source_decision_card","requiredInlineFields":["primary source and exact filters/recipe","Start Import action awaiting approval","for Signal Discovery: compact Source Recommendation in plain language with selected posts, people to check, likely prospects, first review, and fallback","for Signal Discovery: recommended scrape post count and target people-to-check volume","first campaign review size, clearly separate from source sampling","runner-up and why it lost","raw volume","sampled people","sampled fits as n/N plus percentage/range","estimated usable prospects","cleanup risk","what happens after Start Import"],"copyMustAvoid":["lead-source scouting","source scouting","headline-fit","engagers needed","execution slice","ICP","good buyers","real buyers","This approval covers","It does not approve","does not approve filters","filters, messages, sender selection","sender selection, sequence, or sending","Watch link:","campaign-builder URL","repeat the watch URL"],"approvalBoundaryRule":"Use positive Start Import copy only. Include: \"After approval, I will build the source list, add it to the campaign, and review the first 15 leads before we scale.\" Never list future non-approvals.","linkPolicy":"Do not include another watch link in Source Recommendation; describe the Start Import decision only."},{"action":"ask_source_review_choice","uses":"request_user_input","choices":["Approve scraping N recommended LinkedIn posts","Start Import for the approved source list","Revise source","Pause here"],"approvalChoiceLabelsByProvider":{"signal-discovery":"Approve scraping {scrapePostCount} recommended LinkedIn posts?","sales-nav":"Start Import for the approved Sales Nav source list","prospeo":"Start Import for the approved Prospeo source list"},"postApprovalContract":{"singleUseApproval":true,"doNotRepeatAfterApproval":["Source Recommendation","show_source_decision_card","ask_source_review_choice"],"requiredNextActionAfterApproval":"ack once; call import_leads immediately","signalDiscoveryNextTool":"import_leads({ provider: \"signal-discovery\", targetEngagerCount, maxPostsToScrape, confirmed: true })"},"autoSelectIf":"yolo_mode and projected usable pool clears the source quality floor","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]}],"requiredCampaignState":["campaignId","campaignBrief","providerSearchAssociation"],"allowedTools":["AskUserQuestion","request_user_input","update_campaign"],"doNotAllow":["create_campaign","list_senders","save_rubrics","import_leads","confirm_lead_list","queue_cells","start_campaign"],"waitFor":["lead_review_confirmed","revise_leads","confirm_with_user","auto_continue"],"transitions":{"lead_review_confirmed":"auto-execute-leads","revise_leads":"find-leads","confirm_with_user":"auto-execute-leads","auto_continue":"auto-execute-leads"}},{"id":"auto-execute-leads","label":"Materialize confirmed source list","currentStepValue":"auto-execute-leads","reference":"references/step-13-import-leads.md","onEnter":[{"tool":"get_subskill_prompt","requiredValues":{"subskillName":"create-campaign-v2-tail"}},{"tool":"import_leads","requiredFields":["campaignOfferId","selected source/list","sourceListTarget or targetEngagerCount"],"requiredValues":{"salesNavProspeoDefaultSourceListTarget":1000,"signalDiscoveryDefaultEngagerTarget":1500},"modeAddHandshake":{"firstCallReturns":"needsModeSelection when adding to an existing campaign-attached list","requiredFollowup":"retry with mode=add after explicit user/source-state compatibility is confirmed"},"surfaceDedupRatio":true},{"tool":"wait_for_lead_list_ready","repeatUntil":"ready_true_or_cancelled_or_import_failed","requiredValues":{"requireComplete":true},"onImportStillRunning":"re-run wait_for_lead_list_ready; do not call confirm_lead_list just because rows exist","partialOverrideRule":"Only if the user explicitly asks to keep going early may the next confirm_lead_list call pass allowPartialSourceList: true."},{"tool":"confirm_lead_list","requiredFields":["campaignOfferId","selectedLeadListId","reviewBatchLimit"],"requiredValues":{"reviewBatchLimit":15},"capture":["workflowTableId","reviewBatchRowIds"],"requiredPrecondition":"wait_for_lead_list_ready returned ready:true, unless the user explicitly asked to keep going early with a partial list","partialOverrideField":"allowPartialSourceList:true only after explicit user early-continue instruction","mustNotRunWhen":["wait_for_lead_list_ready reason=import_still_running and no explicit early-continue instruction","wait_for_lead_list_ready reason=cancelled","wait_for_lead_list_ready reason=import_failed","missing import job metadata"]},{"tool":"wait_for_campaign_table_ready"},{"tool":"get_rows_minimal","requiredValues":{"tableId":"{workflowTableId}","limit":15},"capture":["reviewBatchRowHash"]},{"action":"summarize_review_batch_and_advance_to_filter_choice","maxCustomerCopyLines":4,"copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"linkPolicy":"Ask add filters vs skip filters without repeating the watch link.","purpose":"ask filter choice immediately"}],"requiredCampaignState":["campaignId","providerSearchAssociation","selectedLeadListId"],"allowedTools":["get_subskill_prompt","import_leads","wait_for_lead_list_ready","confirm_lead_list","wait_for_campaign_table_ready","get_rows_minimal","update_campaign","AskUserQuestion","request_user_input"],"doNotAllow":["get_post_find_leads_scout_registry","Task","spawn_agent","list_senders","queue_cells","start_campaign","enrich_with_prospeo","bulk_enrich_with_prospeo","save_rubrics"],"waitFor":"source_list_confirmed_and_review_sample_ready","transitions":{"source_list_confirmed_and_review_sample_ready":"filter-choice","escalation_triggered":"escalation"},"hardRules":["import_leads_then_repeated_wait_for_lead_list_ready_then_confirm_lead_list_then_wait_for_campaign_table_ready","partial_source_rows_do_not_unblock_confirm_lead_list_without_explicit_user_early_continue","cancelled_or_failed_source_import_stops_before_campaign_table_copy"]},{"id":"filter-choice","label":"Filter choice","currentStepValue":"filter-choice","onEnter":[{"tool":"update_campaign","requiredValues":{"currentStep":"filter-choice","watchNarration.stage":"fit-message"}},{"action":"ask_filter_choice","uses":"request_user_input","choices":["Use filters","Skip filters","Revise source"],"autoSelectIf":"yolo_mode; choose filters unless source is tightly curated or user directed otherwise","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"copyMustInclude":["source rows are in the campaign","add fit filters before message drafting or skip filters"]}],"hardRules":["ask_filter_choice_immediately_after_review_batch_import","do_not_call_get_subskill_prompt_before_filter_choice","do_not_call_get_subskill_asset_before_filter_choice","do_not_call_get_post_find_leads_scout_registry_before_filter_choice","do_not_spawn_prospect_setup_before_filter_choice"],"requiredCampaignState":["campaignId","campaignBrief","selectedLeadListId","workflowTableId"],"allowedTools":["AskUserQuestion","request_user_input","update_campaign","get_campaign_navigation_state"],"doNotAllow":["get_subskill_prompt","get_subskill_asset","get_post_find_leads_scout_registry","Task","spawn_agent","create_campaign","list_senders","import_leads","confirm_lead_list","queue_cells","start_campaign","generate_messages"],"waitFor":["filters_enabled","filters_skipped","revise_leads"],"transitions":{"filters_enabled":"prospect-setup","filters_skipped":"message-generation","revise_leads":"find-leads"}},{"id":"prospect-setup","label":"Filter setup + message drafting","onEnter":[{"action":"persist_add_filters_approval","tool":"update_campaign","when":"filters_enabled","requiredFields":["campaignId","enableICPFilters","currentStep","watchNarration"],"requiredValues":{"enableICPFilters":true,"currentStep":"create-icp-rubric","watchNarration.stage":"fit-message","watchNarration.headline":"Create filter rules","watchNarration.visibleState":"Filter Rules is visible while Codex drafts and saves filters in the parent thread.","watchNarration.nextAction":"Review saved filter rules"},"mustRunBefore":["get_post_find_leads_scout_registry","launch_message_drafting_after_filter_choice","load_filter_reference_in_parent","save_rubrics","ask_filter_rubric_review_choice"]},{"tool":"get_post_find_leads_scout_registry","returns":["post-find-leads-message-scout"],"rule":"normal post-import registry exposes only Message Drafting; filters are parent-thread MCP work"},{"action":"launch_message_drafting_after_filter_choice","mode":"background_agent_when_host_supports_subagents","target":"post-find-leads-message-scout","when":"filters_enabled or filters_skipped after filter-choice answer","doesNotQueueCells":true,"customerNarration":"Message Drafting is preparing while Codex handles filters in the parent thread.","inputs":["campaignId","workflowTableId","brief summary: offer, buyer, source context, safe proof, blocked claims","source summary and source-use rule","3-5 sample workflow-table rows with rowId/name/title/company/signal","optional campaignName, selectedLeadListId, filterChoice"],"forbiddenSiblings":["source-scout-*","any filter background worker"],"handoffCompression":"lean_message_drafting_handoff_no_hashes_no_counts_no_full_row_data"},{"tool":"get_subskill_asset","action":"load_filter_reference_in_parent","when":"filters_enabled","requiredValues":{"subskillName":"create-campaign-v2","assetPath":"references/filter-leads.md"},"rule":"Parent thread uses this reference to draft production rubrics; do not spawn a filter worker."},{"tool":"save_rubrics","when":"filters_enabled","requiredFields":["campaignOfferId","leadScoringRubrics"],"writesCampaignState":"leadScoringRubrics","requiredSideEffects":{"enableICPFilters":true,"currentStep":"create-icp-rubric","watchNarration.headline":"Filter rules saved for review"}},{"action":"ask_filter_rubric_review_choice","uses":"request_user_input","choices":["Approve filters","Revise filters","Pause"],"copyMustInclude":["Filter rules saved for review","These rules prevent wasted sends before I score/import the list.","Recommended because of the researched ICP, source sample, and repeated false-positive patterns.","one pass example and one block example when available","approval is for the saved filter rules","Approve these filter rules."],"autoSelectIf":"yolo_mode and parent saved production-shaped rubrics","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"requiredPrecondition":"save_rubrics succeeded or active campaign rubrics verified"}],"requiredCampaignState":["campaignId","campaignBrief","selectedLeadListId","workflowTableId"],"allowedTools":["get_post_find_leads_scout_registry","get_subskill_asset","save_rubrics","get_campaign","get_rows_minimal","update_campaign","get_campaign_navigation_state","AskUserQuestion","request_user_input","Task","spawn_agent"],"doNotAllow":["create_campaign","list_senders","import_leads","confirm_lead_list","queue_cells","start_campaign","check_rubric","generate_messages"],"waitFor":["filter_rubrics_approved","revise_leads","revise_rubric","revise_messaging"],"hardRules":["after_save_rubrics_currentStep_must_stay_create-icp-rubric_until_filter_approval","filter_approval_required_before_apply-icp-rubric_or_queue_campaign_cells","do_not_move_browser_to_messages_until_filter_leads_step_is_current_or_filters_are_explicitly_skipped","no_prospect_setup_worker_or_deep_prompt_before_filter_choice","message_drafting_after_filter_choice","message_drafting_no_cells","only_message_drafting_may_spawn_background_agent","filters_are_parent_thread_mcp_work","no_post_find_leads_filter_scout_in_normal_path"],"transitions":{"filter_rubrics_approved":"message-generation","revise_leads":"find-leads","revise_rubric":"filter-rubric","revise_messaging":"message-generation","confirm_with_user":"message-review"}},{"id":"filter-rubric","label":"Rubric revision","onEnter":[{"tool":"get_subskill_asset","requiredValues":{"subskillName":"create-campaign-v2","assetPath":"references/filter-leads.md"}},{"tool":"save_rubrics","requiredFields":["campaignOfferId","leadScoringRubrics"],"writesCampaignState":"leadScoringRubrics","requiredSideEffects":{"enableICPFilters":true,"currentStep":"create-icp-rubric","watchNarration.headline":"Filter rules saved for review"}},{"action":"ask_filter_rubric_review_choice","uses":"request_user_input","choices":["Approve filters","Revise filters","Pause"],"copyMustInclude":["These rules prevent wasted sends before I score/import the list.","approval object is filter rules only","approval is for the filter rules","Approve these filter rules."],"autoSelectIf":"yolo_mode and rubrics are production-shaped","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]}],"requiredCampaignState":["campaignId","workflowTableId"],"allowedTools":["get_subskill_asset","save_rubrics","AskUserQuestion","request_user_input"],"doNotAllow":["create_campaign","list_senders","import_leads","confirm_lead_list","update_campaign","queue_cells","start_campaign","check_rubric"],"waitFor":["filter_rubrics_approved","revise_leads","confirm_with_user","auto_continue"],"transitions":{"filter_rubrics_approved":"message-generation","revise_leads":"find-leads","confirm_with_user":"message-generation","auto_continue":"message-generation"}},{"id":"message-generation","label":"Message drafting","onEnter":[{"action":"set_message_review_visible_step_by_filter_choice","tool":"update_campaign","branchRules":["yes after filter approval: currentStep=apply-icp-rubric; wait on Filter Leads","no: currentStep=messages; message review"],"watchNarration.stage":"fit-message"},{"action":"run_or_reconcile_message_draft_builder","target":"post-find-leads-message-scout","toolCallRequiredBeforeDraft":["join already-running Message Drafting when prospect-setup launched it","run Message Drafting via post-find-leads-message-scout only if missing; yolo counts","handoff lean basis only: campaignId, workflowTableId, brief summary, source summary/source-use rule, 3-5 sample workflow-table rows","do not paste copied row counts, brief hashes, review-batch hashes, full reviewBatchRowIds, broad row data, or local debug artifacts into the spawn prompt","branch loads current brief/context and sample rows, full generate-messages prompt, and every required message asset referenced by generate-messages Mode 0","return labeled Markdown only: templateRecommendation, tokenFillRules, renderedGoodSample, status, approveOrReviseRecommendation, validationStatus, outputAt/outputHash, and blocked/retry detail","do not return renderedFallbackSample, risk notes, or qaReceipt on the normal happy path","if no yolo and permission missing, ask once before parent inline fallback","use generic gpt-5.5 xhigh Message Drafting agent if named unavailable"],"stateSource":"message branch-loaded live campaign/table state plus parent-provided sample rows","outputState":"messageDraftRecommendation with internal validation passed","revisionMode":{"when":"revise_messaging, message QA request, or latest user message requests template changes before approve-message","route":"send feedback/QA/rewrite request to post-find-leads-message-scout or generic gpt-5.5 xhigh Message Drafting branch","requiredInputs":["latest user feedback","current messageDraftRecommendation and basisToken/outputHash","lean campaign/table basis and brief summary; branch reloads live state"],"forbiddenParentActions":["rewrite template in parent","QA template in parent from memory","update_campaign_brief before approve-message"],"output":"revised messageDraftRecommendation rendered before request_user_input"},"onlyMessageBackgroundAgent":true,"forbiddenSiblingAgents":["source-scout-*","any filter background worker"],"handoffCompression":"lean_message_drafting_handoff_no_hashes_no_counts_no_full_row_data","finalGateRequiredBeforeReady":"Post-generation final gate: After candidate generation/revision and before returning ready, load get_subskill_prompt({ subskillName: \"create-campaign-v2-validation\" }) as the final internal validation gate."}],"requiredCampaignState":["campaignId","campaignBrief","selectedLeadListId","workflowTableId"],"allowedTools":["get_subskill_prompt","get_campaign","get_rows_minimal","update_campaign","Task","spawn_agent"],"toolRules":["message_drafting_agent_first_no_silent_parent_fallback; yolo counts","on_filters_enabled_path_parent_must_not_enter_message_review_until_save_rubrics_success_and_filter_approval","brief.md, lead-review.md, and lead-sample.json are optional debug context only.","messageDraftRecommendation returns templateRecommendation, tokenFillRules, renderedGoodSample, status, approveOrReviseRecommendation, validationStatus, outputAt, outputHash, and error/retry detail.","messageDraftRecommendation does not return renderedFallbackSample, risk notes, or qaReceipt on the normal happy path.","If campaign/table/sample basis does not match, classify the output stale or blocked.","message_revision_feedback_routes_to_message_drafting_agent_not_parent","message_qa_routes_to_message_drafting_agent_not_parent","message_drafting_loads_full_generate_messages_prompt_all_chunks","message_drafting_loads_all_reference_assets_via_get_subskill_asset","message_drafting_loads_create_campaign_v2_validation_prompt_before_return","message_drafting_handoff_uses_lean_basis_no_hashes_no_counts_no_full_row_id_list","message_drafting_loads_current_campaign_brief_before_drafting","parent_may_load_generate_messages_only_for_explicitly_approved_inline_fallback","before return branch loads create-campaign-v2-validation prompt and runs internal validation"],"doNotAllow":["create_campaign","list_senders","save_rubrics","import_leads","confirm_lead_list","queue_cells","start_campaign","generate_messages","AskUserQuestion","request_user_input"],"waitFor":["message_validation_ready","revise_rubric","revise_messaging"],"transitions":{"message_validation_ready":"message-review","revise_rubric":"filter-rubric","revise_messaging":"message-generation"},"revisionLoop":{"trigger":"user gives copy feedback, asks for QA/update, or chooses revise-messaging","required":["route latest user feedback or QA request to Message Drafting with current recommendation and live campaign/table state","produce a new messageDraftRecommendation with revisionNotes or validationStatus","render revised ## Message Template, ## Rendered Example, and What changed before asking approval"],"blocked":["asking whether an unseen new version is better","reusing the old template after acknowledging feedback","rewriting the template in the parent thread","update_campaign_brief before approve-message","request_user_input or AskUserQuestion during message-generation","QAing the template in the parent thread"],"outputState":"messageDraftRecommendation"},"hardRules":["message_revision_must_render_new_template_before_approval_question","message_revision_saves_only_after_approve_message","message_generation_must_not_call_request_user_input","message_generation_must_transition_to_message_review_only_after_renderable_draft_state","message_drafting_agent_first_no_silent_parent_fallback","message_revision_routes_to_message_drafting_agent","message_qa_routes_to_message_drafting_agent","filter_path_requires_saved_filters_before_message_review","only_message_drafting_may_spawn_background_agent"]},{"id":"message-review","label":"Message review","onEnter":[{"action":"render_message_review_from_state","requiredState":["campaignBrief","selectedLeadListId","workflowTableId","messageDraftRecommendation"],"requiredVisibleLabels":["## Message Template","## Rendered Example","Good token fill:","My take:","Question: approve-message or revise-messaging?","Recommendation:"],"doNotShowByDefault":["Rendered fallback sample","Concerns","QA receipt","Token Notes","Good omit / fallback","Bad fill to avoid","Token Adherence Table"],"internalPersistenceOnly":["Token Fill Rules","Token Fill Examples","fallback guidance","bad-fill avoidance notes","validation notes","QA details"],"copyMustInclude":["one recommended template","one rendered sample","token rules and fallbacks","full list remains paused"],"copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"revisionRenderRule":"After revise_messaging, a message QA request, or user copy feedback, route feedback to Message Drafting and show revised template, rendered example, and What changed before ask_message_review_choice; never ask if an unseen version is better.","parentMustNot":["rewrite template from memory","invent validation summary without Message Drafting output","render qaReceipt, risk notes, or renderedFallbackSample on the normal happy path"]},{"action":"ask_message_review_choice","uses":"request_user_input","choices":["approve-message","revise-messaging"],"copyMustInclude":["approve this message template and continue","nothing sends from this approval"],"autoSelectIf":"yolo_mode and Recommendation is approve-message; revise autonomously when Recommendation is revise-messaging","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"],"requiredPrecondition":"current or revised template and rendered example are visible in this turn","revisionPrecondition":"after revise_messaging, revised template is visible before this question"},{"action":"sync_approved_message_set_to_campaign_brief","tool":"update_campaign_brief","when":"after approve-message","requiredFields":["campaignId","approvedMessageTemplate","Token Fill Rules","Token Fill Examples"],"writesCampaignState":"approvedMessageTemplate","revisionApprovalRule":"If the user requested revisions, write only the latest Message Drafting-approved revised template and token rules after approve-message.","forbiddenBefore":"approve-message"}],"requiredCampaignState":["campaignId","workflowTableId","messageDraftRecommendation"],"allowedTools":["AskUserQuestion","request_user_input","update_campaign_brief","update_campaign","get_rows_minimal"],"doNotAllow":["create_campaign","list_senders","save_rubrics","import_leads","confirm_lead_list","start_campaign"],"waitFor":["message_approved","revise_messaging"],"transitions":{"message_approved":"validate-sample","revise_messaging":"message-generation"}},{"id":"validate-sample","label":"Validate campaign-table execution slice","currentStepValue":"apply-icp-rubric","reference":"references/sample-validation-loop.md","visibleStepRule":"Filter Leads is reached only after saved-filter approval; on approve-message, save the template and queue bounded Enrich Prospect cells through selector-based campaign processing.","onEnter":[{"tool":"update_campaign","requiredValues":{"currentStep":"apply-icp-rubric","watchNarration.stage":"fit-message"},"watchNarrationRule":"Say the template is saved and Filter Leads is now running the bounded enrichment and scoring pass."},{"tool":"queue_campaign_cells","requiredFields":["workflowTableId","columnRole","rowSelector"],"requiredValues":{"columnRole":"enrich","rowSelector":{"type":"reviewBatch"},"forceRerun":false},"targetCountSource":"WorkflowTable.config.mcp.reviewBatch.rowCount (default 15)"},{"tool":"wait_for_campaign_processing","requiredFields":["workflowTableId","minPassedCount"],"requiredValues":{"minPassedCount":1},"readVia":"stats_only_tool_result","timeoutGuidance":"If this times out, do not repoll identical args; use partial diagnostics to revise filters or surface blocked sample state.","customerSummaryPattern":["{checked} leads checked","{passed} passed fit scoring","{blocked} blocked before sending","full list remains paused until approval"]},{"action":"handle_partial_or_timeout_sample","customerStatus":"sample-needs-revision","rule":"Do not repeat waits indefinitely; surface partial status and route to revision.","copyMustInclude":"completed, passed, pending, blocked before sending, and full list remains paused"}],"requiredCampaignState":["campaignId","workflowTableId","approvedMessageTemplate","filterRubricsApproved when enableICPFilters=true"],"allowedTools":["get_subskill_asset","queue_campaign_cells","select_campaign_cells","get_campaign_table_schema","wait_for_campaign_processing","update_campaign","AskUserQuestion","request_user_input"],"doNotAllow":["import_leads","list_senders","start_campaign","enrich_with_prospeo","bulk_enrich_with_prospeo","check_rubric"],"hardRules":["campaign_processing_waits_are_stats_only_by_default","queue_review_batch_by_selector_never_fetch_rows_for_cell_ids","timeout_never_repeats_without_customer_handoff","timeout_or_underfloor_sample_never_advances_to_settings"],"waitFor":["sample_validated","sample_revision_required"],"transitions":{"sample_validated":"auto-execute-messaging","sample_revision_required":"lead-review","revise_leads":"find-leads","revise_rubric":"filter-rubric","escalation_triggered":"escalation"}},{"id":"auto-execute-messaging","label":"Generate initial campaign-row messages","currentStepValue":"auto-execute-messaging","references":["references/parallel-critique-protocol.md","references/thomas-variant-selection.md","references/sellable-cleanup-rules.md","references/step-15-re-cascade.md"],"onEnter":[{"tool":"queue_campaign_cells","batchSize":100,"when":"any passing row has pending, empty, or stale Generate Message cell","requiredFields":["workflowTableId","columnRole","rowSelector"],"requiredValues":{"columnRole":"generateMessage","rowSelector":{"type":"needsGeneratedMessage"},"forceRerun":false},"cellSource":"selector-engine needsGeneratedMessage rows using approved campaign brief template"},{"tool":"wait_for_campaign_processing","purpose":"wait_for_first_current_revision_generated_message","requiredValues":{"minGeneratedMessages":1,"templateRevision":"current"},"readVia":"stats_only_tool_result","invariant":"A generated message implies the pass gate; stale or wrong-revision messages are excluded from readiness."},{"action":"observe_generate_message_results","reference":"references/step-15-re-cascade.md"},{"action":"enforce_token_contract","modeFromConfig":"messaging.tokenContract"},{"action":"optional_critique_pass","enabledFromConfig":"messaging.critique.enabled","protocol":"references/parallel-critique-protocol.md","sampleSizeFromConfig":"messaging.critique.sampleSize","budgetUsdCapFromConfig":"messaging.critique.budgetUsdCap","perCriticTimeoutFromConfig":"messaging.critique.perCriticTimeoutSeconds","totalTimeoutFromConfig":"messaging.critique.totalTimeoutSeconds","criticsFromConfig":"messaging.critique.critics","enforceFinalizerPassFromConfig":"messaging.critique.synthesis.enforceFinalizerPass","rejectOnFakeProofFromConfig":"messaging.critique.rejectOnFakeProof","rejectOnUnsupportedTokenFromConfig":"messaging.critique.rejectOnUnsupportedToken","onBudgetTrip":"halt_critique_continue_plain_tail","onPerCriticTimeout":"drop_critic_proceed_with_remaining","onTotalTimeout":"persist_plain_message_for_row","onTokenContractViolation":"persist_plain_message_for_row","onFakeProof":"persist_plain_message_for_row"},{"action":"optional_opus_subset","enabledFromConfig":"messaging.critique.opus.enabled","selection":"references/thomas-variant-selection.md","maxMessagesPerPassFromConfig":"messaging.critique.opus.maxMessagesPerPass","budgetUsdCapFromConfig":"messaging.critique.opus.budgetUsdCap","onOpusBudgetTrip":"halt_opus_continue_non_opus","onOpusTokenContractViolation":"fallback_to_non_opus_rewrite"},{"tool":"update_campaign","requiredValues":{"currentStep":"auto-execute-messaging","watchNarration.stage":"review-ready"},"watchNarrationRule":"Say the first passing generated message is ready in Messages; next is review before Settings."},{"action":"ask_generated_message_review_choice","uses":"request_user_input","choices":["Approve reviewed draft rows and continue to Settings","Revise filters","Revise message template","Pause here"],"copyMustInclude":["approve the reviewed draft rows and continue to Settings","tokens resolved","company/person match","proof claim","prospect angle","language/tone when known","obvious bad fits","Would I take this call?","weak personalization can burn the sender's reputation","full list remains paused","nothing sends from this approval"],"autoSelectIf":"yolo_mode and the first passing generated message clears the quality floor","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]}],"allowedTools":["get_subskill_asset","get_campaign_table_schema","select_campaign_cells","queue_campaign_cells","wait_for_campaign_processing","revise_message_template_and_rerun","update_campaign","AskUserQuestion","request_user_input"],"doNotAllow":["import_leads","list_senders","start_campaign","generate_messages"],"hardRules":["generated_message_count_excludes_stale_or_wrong_revision_messages","message_template_revision_uses_brief_update_then_generate_message_rerun","do_not_overwrite_generated_message_cells_directly","critique_failure_never_escalates","critique_sample_size_bounded_by_config","first_passing_generated_message_unblocks_review","critics_fixed_at_targeting_copy_voice","synthesis_enforces_message_token_contract","opus_reserved_for_highest_value_subset","proposed_token_never_persisted_in_rewrite"],"waitFor":["generated_messages_approved","sample_revision_required"],"transitions":{"generated_messages_approved":"awaiting-user-greenlight","revise_filters":"filter-rubric","revise_messaging":"message-generation","escalation_triggered":"escalation"}},{"id":"awaiting-user-greenlight","label":"Settings, sender, sequence, and greenlight","currentStepValue":"awaiting-user-greenlight","reference":"references/final-handoff-contract.md","onEnter":[{"tool":"get_campaign"},{"tool":"list_senders","purpose":"surface available connected senders only at Settings"},{"tool":"update_campaign","requiredValues":{"currentStep":"settings","watchNarration.stage":"review-ready"},"watchNarrationRule":"Say message review is complete and the app is on Settings for sender choice. Mention lead research/filtering already happened outside the user's LinkedIn account and nothing sends until Start."},{"action":"surface_sender_and_slack_handoff","requiredVisibleContent":["connect or select a LinkedIn sender","Lead research and filtering already happened outside your LinkedIn account.","This account is only used for approved sending after final launch.","Nothing sends until the final Start step.","Slack reply review","recommended sequence","final launch confirmation is still ahead"],"copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]},{"action":"ask_sender_selection","uses":"request_user_input","singleChoice":true,"choices":["Use this connected sender","Connect a different sender in Settings","Pause here"],"autoSelectIf":"yolo_mode and exactly one safe connected sender is available","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]},{"action":"attach_selected_sender","tool":"update_campaign","when":"user selected an available connected sender","requiredValues":{"senderIds":["{selectedSenderId}"],"currentStep":"sequence","watchNarration.stage":"review-ready"},"watchNarrationRule":"Say the sender was attached and the app is moving to Sequence review; sequence remains editable and nothing sends until Start."},{"tool":"attach_recommended_sequence","when":"after senderIds are attached","requiredValues":{"campaignId":"{campaignId}","currentStep":"send","watchNarration.stage":"review-ready"},"watchNarrationRule":"The sequence tool owns this visible beat: say the recommended follow-up sequence is attached, the app is on final launch review, and it is still not sending until Start."},{"action":"ask_final_launch_greenlight","uses":"request_user_input","singleChoice":true,"choices":["Start campaign","Review campaign first","Pause here"],"copyMustInclude":["quality confidence means sample messages and prospect angle were checked","launch confidence means sender, sequence, and Start are ready","approved messages begin sending according to the sequence","replies and meetings follow connected settings","you can monitor and pause","no hidden extra approval disappears after clicking Start"],"onUserStart":"claude-greenlight","neverAutoSelectInYolo":true,"copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]}],"allowedTools":["get_campaign","get_campaign_navigation_state","list_senders","update_campaign","attach_recommended_sequence","AskUserQuestion","request_user_input"],"doNotAllow":["start_campaign","import_leads"],"autoStart":false,"watchRequired":true,"waitFor":["sender_connection_required","sender_attached","sequence_attached","ready_to_launch","user_greenlight","ui_start_detected"],"transitions":{"sender_connection_required":"awaiting-user-greenlight","sender_attached":"awaiting-user-greenlight","sequence_attached":"awaiting-user-greenlight","ready_to_launch":"awaiting-user-greenlight","user_greenlight":"claude-greenlight","ui_start_detected":"running"}},{"id":"claude-greenlight","label":"Explicit launch","reference":"references/final-handoff-contract.md","onEnter":[{"tool":"get_campaign"},{"action":"verify_sequence_and_current_step_before_start","requiredState":["workflowTableId","senderIds","sequenceTemplate","at least one approved generated message","currentStep in awaiting-user-greenlight|claude-greenlight|send"]},{"tool":"start_campaign","requiredFields":["campaignId"],"persistsCurrentStep":"running","watchNarrationRule":"After start_campaign succeeds, the running state must say the final greenlight was accepted, the campaign is now live/running, and the user can watch progress from the campaign."}],"allowedTools":["get_campaign","attach_recommended_sequence","start_campaign","AskUserQuestion","request_user_input"],"watchRequired":true,"waitFor":"campaign_started","transitions":{"campaign_started":"running"}},{"id":"running","label":"Campaign is live","currentStepValue":"running","onEnter":[{"action":"surface_campaign_live_confirmation_without_watch_link","copyMustAvoid":["Watch link:","campaign-builder URL","repeat the watch URL"]}],"allowedTools":["get_campaign","AskUserQuestion","request_user_input"],"doNotAllow":["start_campaign"],"terminal":true},{"id":"escalation","label":"Escalation","reference":"references/escalation-ladder.md","allowedTools":["AskUserQuestion","request_user_input"],"doNotAllow":["start_campaign","import_leads"],"transitions":{"revise_brief":"brief-interview","revise_leads":"find-leads","revise_rubric":"filter-rubric","revise_messaging":"message-generation","abort":"abort"}},{"id":"abort","label":"Abort","allowedTools":["AskUserQuestion","request_user_input"],"terminal":true}]}
@@ -224,8 +224,8 @@ reach for an em dash — they use commas, periods, parentheses, or
224
224
  a hyphen-minus (`-`) when they want a pause. LLMs default to em
225
225
  dashes for rhythm because they were trained on edited published
226
226
  prose where em dashes are frequent. A message with even ONE em dash
227
- reads as AI-polished, not hand-typed. Surfaced during Phase 94
228
- Skillsync run (Plan 07): generator self-declared "NO em dashes" as
227
+ reads as AI-polished, not hand-typed. Surfaced during a Skillsync
228
+ run: generator self-declared "NO em dashes" as
229
229
  an invariant but still emitted one in the Selected Winner's Block
230
230
  2 because the catalog did not yet codify the pattern.
231
231
 
@@ -349,7 +349,7 @@ may be off, but this seemed relevant."`
349
349
  2. Name it `Tell #N` with a short descriptive title.
350
350
  3. Fill in Pattern / Why / Allowed alternative / Severity.
351
351
  4. The Filter 8 check automatically picks it up — do not touch
352
- `thomas-revision-filters.md` Filter 8 spec when adding tells.
352
+ `sellable-cleanup-rules.md` Filter 8 spec when adding tells.
353
353
  5. Add a corresponding test case in
354
354
  `tests/scripts/skill-references-substance-filters.test.ts` if
355
355
  the new tell needs regression coverage.