@sellable/mcp 0.1.142 → 0.1.144

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 (30) hide show
  1. package/README.md +5 -3
  2. package/agents/post-find-leads-message-scout.md +47 -3
  3. package/agents/registry.json +3 -7
  4. package/dist/index-dev.js +0 -0
  5. package/dist/index.js +0 -0
  6. package/dist/server.js +59 -29
  7. package/dist/tools/auth.js +5 -5
  8. package/dist/tools/leads.js +107 -8
  9. package/dist/tools/processing.d.ts +1 -0
  10. package/dist/tools/prompts.js +3 -3
  11. package/dist/tools/rubrics.js +14 -9
  12. package/package.json +1 -1
  13. package/skills/create-campaign/SKILL.md +52 -32
  14. package/skills/create-campaign-brief/SKILL.md +4 -0
  15. package/skills/create-campaign-v2/SKILL.md +59 -9
  16. package/skills/create-campaign-v2/SOUL.md +21 -12
  17. package/skills/create-campaign-v2/core/flow.v2.json +54 -18
  18. package/skills/create-campaign-v2/core/policy.md +35 -39
  19. package/skills/create-campaign-v2/references/draft-lifecycle.md +20 -104
  20. package/skills/create-campaign-v2/references/filter-leads.md +199 -525
  21. package/skills/create-campaign-v2/references/final-handoff-contract.md +5 -5
  22. package/skills/create-campaign-v2/references/message-review-safety-gate.md +109 -28
  23. package/skills/create-campaign-v2/references/sample-validation-loop.md +5 -2
  24. package/skills/create-campaign-v2/references/step-15-re-cascade.md +2 -3
  25. package/skills/create-campaign-v2/references/watch-guide-narration.md +37 -22
  26. package/skills/create-campaign-v2/references/watch-link-handoff.md +1 -1
  27. package/skills/create-campaign-v2-tail/SKILL.md +26 -13
  28. package/skills/research/config.json +9 -0
  29. package/dist/tools/registry.d.ts +0 -4186
  30. package/dist/tools/registry.js +0 -59
@@ -86,7 +86,7 @@ or tool discovery. Start in product language:
86
86
  ```text
87
87
  I’ll help you launch this as a Sellable campaign. First I’ll resolve the
88
88
  client/company this campaign is for, then I’ll turn that into a campaign brief
89
- before any leads are imported or anything can send.
89
+ before we move into lead sourcing.
90
90
  ```
91
91
 
92
92
  If a linked/local skill file is stale or missing, silently use the installed
@@ -102,8 +102,14 @@ clear business decisions, tradeoffs, and approval gates. Use product language:
102
102
  - "a couple setup choices", not `request_user_input`
103
103
  - "campaign brief", not prompt artifact
104
104
  - "lead source", not provider internals unless comparing source options
105
- - "I can create a draft shell for you to watch, but no leads import and nothing
106
- sends until you approve", not mutation jargon
105
+ - "I can create a draft shell for you to watch with approval gates before
106
+ sourcing", not mutation jargon
107
+
108
+ Approval and safety copy should be tasteful. State what the current approval
109
+ covers once, in one short sentence, then move on. Do not append repeated
110
+ "nothing starts / no leads import / no sending" disclaimers to routine progress
111
+ updates. Use positive gate language like "Next gate: selected-post scrape" or
112
+ "Approval covers scouting/search only" instead of long negative lists.
107
113
 
108
114
  When explaining lead-source decisions, show the concrete counts behind the
109
115
  logic: lanes searched, timeframe, raw result counts, finalist posts or preview
@@ -127,7 +133,7 @@ authorizes scouting/search only. The gate should say:
127
133
  - why that lane fits the buyer, offer, and likely public activity
128
134
  - what will be tested next
129
135
  - the fallback lane if relevant posts or ICP engagement look thin
130
- - that approval authorizes scouting/search only, not lead import or sending
136
+ - what approval covers in one concise line
131
137
 
132
138
  Do not surface blanket source heuristics as product copy. Make the
133
139
  recommendation specific to the campaign. If Signal Discovery is recommended,
@@ -142,6 +148,20 @@ Signal Discovery, name how many selected posts will be scraped, the target
142
148
  engager/source-candidate volume, and the bounded review-batch size. For Sales
143
149
  Nav or Prospeo, name the specific approved import lane. Do not call
144
150
  `import_leads` or `confirm_lead_list` until this second approval is granted.
151
+ For Signal Discovery, the customer-facing approval card must use the exact
152
+ action shape "Approve scraping N Signal Discovery posts?" and the chat summary
153
+ should be a compact `## Source Recommendation` block with:
154
+
155
+ - goal: about 300 good-fit prospects after cleanup, enrichment, and filters
156
+ - working assumption: about 15% of raw post engagers become good-fit prospects
157
+ - engagers needed: about 2,000 raw engagers
158
+ - a selected-post table with post author/topic, why it fits, and visible
159
+ engagement
160
+ - total visible pool and estimated good-fit pool
161
+ - first pass: build the source list, then import only 15 leads into the review
162
+ batch
163
+ - fallback: switch to Sales Nav recent activity if the review batch is
164
+ vendor-heavy, agency-heavy, or off-ICP
145
165
 
146
166
  When the user has not supplied a source and multiple source angles are viable,
147
167
  scout those angles as independent branches when the host can actually do it:
@@ -159,8 +179,8 @@ The create-campaign-v2 subskill calls `get_source_scout_registry` before
159
179
  dispatch so the current registry, not this copy, is the runtime source of truth.
160
180
  If the host runs them sequentially or the named agents are unavailable, do not
161
181
  claim they ran in parallel and do not surface install status to the customer. In
162
- chat, call the downstream copy stage `message generation`;
163
- `message-validation.md` is only an internal proof artifact.
182
+ chat, call the downstream copy stage `message generation`; message validation is
183
+ only an internal approval proof.
164
184
 
165
185
  For campaign-attached Signal Discovery sampling, promote/select the exact posts
166
186
  with `select_promising_posts` before `fetch_post_engagers` so the user can see
@@ -168,19 +188,17 @@ which posts are being sampled in the watched app. The watch guide should say
168
188
  that we are pulling sample engagers from these posts to confirm the ICP is
169
189
  actually engaging and the source is viable.
170
190
 
171
- After find-leads returns a lead source and the user approves it, use the same
172
- registry pattern for the two post-lead branches. The create-campaign-v2 subskill
173
- calls `get_post_find_leads_scout_registry`, then launches the returned
174
- filter-leads scout and message-generation scout together when real subagents are
175
- available and the current session exposes the returned names. Message
176
- generation is the provisional Message Draft Builder: it may start after the
177
- review batch exists, including while the user is on filter choice, but workflow
178
- cell execution must wait. After rubrics are saved, do not queue enrichment,
179
- filtering, or Generate Message cells until the user approves the message
180
- template. AI Generated is an explicit opt-out that cancels or ignores the
181
- background template draft. If the post-lead agents are absent, the main thread
182
- still orchestrates the same branches from the compact context with MCP
183
- tools/assets.
191
+ After the bounded review batch exists, use the same registry pattern for
192
+ post-lead work. The create-campaign-v2 subskill calls
193
+ `get_post_find_leads_scout_registry`, then launches the returned
194
+ message-generation scout immediately when real subagents are available and the
195
+ current session exposes the returned name. If the user chooses filters, launch
196
+ the filter-leads scout then and join it with the already-running or completed
197
+ message draft before message review. Workflow cell execution still waits for
198
+ filter and template approval. AI Generated is an explicit opt-out that cancels
199
+ or ignores the background template draft. If the post-lead agents are absent,
200
+ the main thread still orchestrates the same branches from the compact context
201
+ with MCP tools/assets.
184
202
 
185
203
  Use rendered Markdown for user review surfaces, not fenced code blocks. Keep
186
204
  lines short, use indexed section labels and bullets, and translate internal
@@ -412,7 +430,7 @@ First I’ll resolve the client/company this campaign is for. I’ll use that
412
430
  context to choose the target, offer, proof, and lead source.
413
431
 
414
432
  Then I’ll turn that into a campaign brief for you to approve before any leads
415
- are imported or anything can send.
433
+ are sourced.
416
434
  ```
417
435
 
418
436
  Do not silently ask Codex intake or approval questions as plain chat when
@@ -597,7 +615,7 @@ updates.
597
615
  supplemental approval checklist, not a replacement for the long prompt. Use
598
616
  campaign state, campaign brief content, selected source state, and imported
599
617
  review-batch rows as the source of truth; do not read stale local markdown,
600
- inspect the database directly, or synthesize `message-validation.md` from
618
+ inspect the database directly, or synthesize local validation artifacts from
601
619
  general knowledge.
602
620
  5. Create the campaign shell early with the v1 brief so the user can open the
603
621
  watch link and see useful setup state immediately. Import only the first
@@ -609,9 +627,11 @@ updates.
609
627
  call `mcp__sellable__update_campaign({ campaignId, enableICPFilters: true, currentStep: "create-icp-rubric", watchNarration })`
610
628
  so the watched app moves to Filter Rules while rubrics are drafted/saved.
611
629
  After rubrics save, move the watched app to `apply-icp-rubric` / Filter
612
- Leads and say the fit rules are saved; approve the message template next;
613
- after approval, queue the bounded review-batch
614
- `enrichCellId` cells to kick off enrichment/filtering.
630
+ Leads and say the fit rules are saved; approve the message template next
631
+ while the browser stays on Filter Leads. After approval, save the template
632
+ to the campaign brief, then queue the bounded review-batch `enrichCellId`
633
+ cells to kick off enrichment/filtering. Move to Messages only after at
634
+ least one review row passes and Generate Message cells are running or ready.
615
635
  Product Generate Message cells must not run from the background template
616
636
  path before that template/token approval.
617
637
  Do not ask the user to approve the brief before shell creation unless they
@@ -621,14 +641,14 @@ updates.
621
641
  visible work so the user can watch progress in the app: `create-offer` for
622
642
  the brief, `pick-provider` or the selected provider step while sourcing,
623
643
  `filter-choice` after the 15-row review batch, `create-icp-rubric` as soon
624
- as filters are approved, `apply-icp-rubric` after rubrics save, `messages`
625
- for the Use Template / AI Generated mode
626
- choice, `auto-execute-messaging` for approved
627
- message work or the product's AI-generated path, `awaiting-user-greenlight`
628
- for the final handoff, `settings` for sender selection, `sequence` after
629
- sender attach, and `send` once the recommended sequence is attached.
630
- `validate-sample` is recovery/legacy only if reached. Do not advance the
631
- step backward.
644
+ as filters are approved, `apply-icp-rubric` after rubrics save and while
645
+ waiting for message-template approval, `validate-sample` while the approved
646
+ template unlocks bounded enrichment/filter scoring on Filter Leads,
647
+ `auto-execute-messaging` after at least one row passes and review-batch
648
+ messages are being generated or reviewed, `awaiting-user-greenlight` only
649
+ after generated review-batch messages are approved, `settings` for sender
650
+ selection, `sequence` after sender attach, and `send` once the recommended
651
+ sequence is attached. Do not advance the step backward.
632
652
  7. Keep `selectedLeadListId` as the source list and `workflowTableId` as the
633
653
  campaign table. Do not use disk files as the post-mint source of truth.
634
654
  8. Do not ask the user to run another command.
@@ -6,6 +6,10 @@ visibility: internal
6
6
 
7
7
  # Create Campaign Brief
8
8
 
9
+ Legacy/internal only. This standalone brief-first artifact path is not used by
10
+ the public `create-campaign` wrapper or normal shell-first `create-campaign-v2`
11
+ execution.
12
+
9
13
  You are a Sellable campaign strategist. Build one high-level `brief.md v1` from
10
14
  a LinkedIn URL, optional customer materials, quick research, one recommended
11
15
  campaign thesis, rough ICP mechanics, anti-buyer filters, invisible internal
@@ -47,8 +47,11 @@ for debug output.
47
47
  rows.
48
48
  11. Review and approve/revise the message.
49
49
  12. Sync the approved template into the campaign brief.
50
- 13. Validate the bounded review batch, then move to Settings, sender, sequence,
51
- and explicit launch greenlight.
50
+ 13. After message approval, keep the watched app on Filter Leads while the
51
+ bounded enrichment/filter cascade starts.
52
+ 14. Move to Messages only after at least one review row passes, generate and
53
+ review bounded messages, then hand off to Settings, sender, sequence, and
54
+ explicit launch greenlight.
52
55
 
53
56
  There is no normal approval-packet, commit-gate, atomic-mint, or local
54
57
  artifact-validation step. Those belong only to legacy validation/rehearsal
@@ -151,10 +154,48 @@ After scouting, show a second approval gate for the concrete source action. For
151
154
  Signal Discovery, this gate must say how many selected posts will be scraped,
152
155
  the target engager/source-candidate volume, the bounded campaign review-batch
153
156
  size, the cleanup risk, and the fallback if the selected posts look wrong. The
154
- approval label should describe the action, such as "Scrape 2 selected posts for
155
- the bounded review batch." For Sales Nav or Prospeo, the label should name the
156
- specific search/import lane. Do not call `import_leads` or `confirm_lead_list`
157
- until this second source-action approval is granted.
157
+ approval label must describe the action with the count, such as "Approve
158
+ scraping 3 Signal Discovery posts?" For Sales Nav or Prospeo, the label should
159
+ name the specific search/import lane. Do not call `import_leads` or
160
+ `confirm_lead_list` until this second source-action approval is granted.
161
+
162
+ For Signal Discovery, use this compact source-action approval shape after
163
+ selected posts exist:
164
+
165
+ ```markdown
166
+ ## Source Recommendation
167
+
168
+ Use Signal Discovery first.
169
+
170
+ **Goal:** ~300 good-fit prospects after cleanup, enrichment, and filters<br>
171
+ **Working assumption:** ~15% of raw post engagers become good-fit prospects<br>
172
+ **Engagers needed:** ~2,000 raw engagers
173
+
174
+ ### Selected posts
175
+
176
+ | Post | Why it fits | Visible engagement |
177
+ | ---------------- | ----------------------------------------------- | -----------------: |
178
+ | Dylan Power | Claude outbound system | ~1,571 |
179
+ | Fivos Aresti | Replacing Clay outbound with Claude Code | ~734 |
180
+ | Divyanshi Sharma | LinkedIn lead-gen system built with Claude Code | ~508 |
181
+
182
+ **Total visible pool:** ~2,813 engagers<br>
183
+ **Estimated good-fit pool at 15%:** ~420 prospects before dedupe/risk cleanup
184
+
185
+ ### Recommendation
186
+
187
+ Approve scraping these 3 posts.
188
+
189
+ This gives enough volume to target ~300 good-fit prospects after cleanup, while
190
+ keeping the source tied to people already engaging with Claude Code outbound /
191
+ AI-native sales workflows.
192
+
193
+ **First pass:** build the source list, then import only 15 leads into the
194
+ review batch so we can inspect quality before scaling.
195
+
196
+ **Fallback:** if the review batch is too vendor-heavy, agency-heavy, or
197
+ off-ICP, switch to Sales Nav recent activity.
198
+ ```
158
199
 
159
200
  A source recommendation must show concrete evidence: source lane, filters or
160
201
  recipe, raw volume, sample size, sampled fits as n/N plus percentage/range,
@@ -169,8 +210,15 @@ customer-facing source-choice labels.
169
210
 
170
211
  After `confirm_lead_list` imports a non-empty bounded review batch and
171
212
  `get_rows_minimal({ tableId: workflowTableId })` proves rows exist, call
172
- `get_post_find_leads_scout_registry`. The filter and message branches use live
173
- CampaignOffer/source/table state as the source of truth. Debug markdown/json
213
+ `get_post_find_leads_scout_registry` and start the Message Draft Builder branch
214
+ immediately when the current host exposes that returned agent. Do this before
215
+ asking the filter-choice question. If no real background branch can start, say
216
+ the real sequence and do not claim background drafting is running.
217
+
218
+ The message branch uses live CampaignOffer/source/table state as the source of
219
+ truth and may draft while the user is choosing filters. It does not write
220
+ message cells, enrich rows, attach sequences, or unlock Settings. The Lead Fit
221
+ Builder branch starts only after the user chooses filters. Debug markdown/json
174
222
  artifacts are optional only.
175
223
 
176
224
  When the user chooses filters, immediately call
@@ -198,7 +246,9 @@ get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/
198
246
  ```
199
247
 
200
248
  Do not load the full `generate-messages` prompt in the create-campaign parent
201
- thread unless you are executing the parent-thread fallback for that branch.
249
+ thread unless you are executing the parent-thread fallback for the actual
250
+ message-draft branch. Parent-thread template approval uses only the compact
251
+ message-review safety gate.
202
252
 
203
253
  ## Hard Gates
204
254
 
@@ -35,7 +35,7 @@ tell them what they will see next.
35
35
  is missing.
36
36
  - "lead source" beats provider internals unless comparing options.
37
37
  - "I’ll create the campaign shell with the brief so you can watch it fill in,
38
- but no leads import and nothing sends yet" beats mutation jargon.
38
+ with approval gates before sourcing" beats mutation jargon.
39
39
  - "I’m turning this into a brief now" beats "I’m persisting the draft."
40
40
  - "Sorry, this is taking a little longer than expected" is appropriate when a
41
41
  step overruns its estimate. Do not over-apologize; one calm acknowledgment is
@@ -148,9 +148,9 @@ unless the user asks for them.
148
148
  Good opening:
149
149
 
150
150
  ```text
151
- I’ll help you launch this as a Sellable campaign. First I’ll resolve the
152
- client/company this campaign is for, then I’ll turn that into a campaign brief
153
- before any leads are imported or anything can send.
151
+ I’ll help you launch this as a Sellable campaign. First I’ll confirm who we’re
152
+ sending from and which company this is for, then I’ll turn that into a campaign
153
+ brief before lead sourcing or anything can send.
154
154
  ```
155
155
 
156
156
  Good identity setup:
@@ -236,6 +236,13 @@ source. That approval only authorizes scouting/search. Second, after the
236
236
  source evidence exists, show counts, samples, fit math, cleanup risk, and ask
237
237
  for source approval before import.
238
238
 
239
+ For Signal Discovery, the second gate is not "approve source" in the abstract.
240
+ It is a concrete scrape approval: show a compact `## Source Recommendation`
241
+ with the ~300 good-fit prospect goal, 15% raw-engager assumption, selected-post
242
+ table, total visible pool, estimated good-fit pool, first-pass 15-row review
243
+ batch, and fallback. The approval question should be "Approve scraping N Signal
244
+ Discovery posts?"
245
+
239
246
  ## Parallelism + Naming
240
247
 
241
248
  Source selection is sequential by default. Start with the first recommended
@@ -257,13 +264,15 @@ scout loads only its matching provider prompt. If source work is sequential,
257
264
  keep the output numeric but do not claim the source scout was parallel or
258
265
  surface install status to the customer.
259
266
 
260
- For post-lead work, call `get_post_find_leads_scout_registry` after source
261
- approval and use the returned canonical `name` values. Launch both returned
262
- scouts in the same assistant turn/message when real subagents are available:
263
- `post-find-leads-filter-scout` and `post-find-leads-message-scout`. This is the
264
- same registry pattern as source scouting, but the trigger is approved
265
- find-leads output and the join gate is both `lead-filter.md` and
266
- `message-validation.md`.
267
+ For post-lead work, call `get_post_find_leads_scout_registry` after
268
+ `confirm_lead_list` imports a non-empty bounded review batch and
269
+ `get_rows_minimal` proves rows exist. Start `post-find-leads-message-scout`
270
+ immediately when real subagents are available, before asking the filter-choice
271
+ question. Start `post-find-leads-filter-scout` only after the user chooses
272
+ filters. This is the same registry pattern as source scouting, but the trigger
273
+ for message drafting is review-batch import, not filter approval. The join gate
274
+ is live branch readiness: saved rubrics or a resolved skip-filter choice, plus a
275
+ message recommendation grounded in the same campaign/table basis.
267
276
 
268
277
  Only promise parallel post-lead work when parallel work actually started. If the
269
278
  host cannot or should not launch background branches, say the real sequence:
@@ -276,7 +285,7 @@ Do not say `kicking off two workstreams`, `in parallel`, or `background` as
276
285
  aspirational copy.
277
286
 
278
287
  Call the post-filter message stage `message generation` in chat.
279
- `message-validation.md` is an internal proof artifact, not the workstream name.
288
+ Message validation is an internal approval proof, not the workstream name.
280
289
 
281
290
  Be explicit about what has and has not happened:
282
291
 
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "v2.1-compact",
3
3
  "workflow": "create-campaign-v2",
4
- "principle": "CampaignOffer state and the watch link are canonical from the first brief onward. The active customer path is shell-first and state-first: create the watchable campaign shell with the brief, attach source/search state to that CampaignOffer, import one bounded review batch, persist rubrics and approved message template, validate the review batch, then hand off to Settings, sequence, and explicit start.",
4
+ "principle": "CampaignOffer state and the watch link are canonical from the first brief onward. The active customer path is shell-first and state-first: create the watchable campaign shell with the brief, attach source/search state to that CampaignOffer, import one bounded review batch, persist rubrics, wait on Filter Leads for approved message-template review, save the approved template, validate the bounded review batch, generate and review bounded messages, then hand off to Settings, sequence, and explicit start.",
5
5
  "normalCustomerPath": "Use campaign state, MCP tool responses, and concise watchNarration. Do not create, read, link, or surface local draft files in normal customer runs.",
6
6
  "legacyCompatibility": {
7
7
  "validationSubskill": "create-campaign-v2-validation",
@@ -460,6 +460,7 @@
460
460
  "requiredInlineFields": [
461
461
  "primary source and exact filters/recipe",
462
462
  "specific source action awaiting approval",
463
+ "for Signal Discovery: Source Recommendation markdown with goal ~300 good-fit prospects, ~15% raw-engager fit assumption, ~2,000 raw engagers needed, selected-post table, total visible pool, estimated good-fit pool, first pass, and fallback",
463
464
  "for Signal Discovery: selected post count and target engager/source-candidate volume",
464
465
  "bounded review batch size",
465
466
  "runner-up and why it lost",
@@ -475,13 +476,13 @@
475
476
  "action": "ask_source_review_choice",
476
477
  "uses": "request_user_input",
477
478
  "choices": [
478
- "Scrape selected posts for the bounded review batch",
479
+ "Approve scraping N Signal Discovery posts",
479
480
  "Run the approved source import for the bounded review batch",
480
481
  "Revise source",
481
482
  "Pause here"
482
483
  ],
483
484
  "approvalChoiceLabelsByProvider": {
484
- "signal-discovery": "Scrape selected posts for the bounded review batch",
485
+ "signal-discovery": "Approve scraping {selectedPostCount} Signal Discovery posts?",
485
486
  "sales-nav": "Import the approved Sales Nav review batch",
486
487
  "prospeo": "Import the approved Prospeo review batch"
487
488
  }
@@ -579,7 +580,18 @@
579
580
  {
580
581
  "action": "launch_message_draft_builder_after_review_batch_import",
581
582
  "tool": "get_post_find_leads_scout_registry",
582
- "requiresNonEmptyRows": true
583
+ "target": "post-find-leads-message-scout",
584
+ "requiresNonEmptyRows": true,
585
+ "mustRunBefore": [
586
+ "filter-choice question",
587
+ "filter approval",
588
+ "save_rubrics"
589
+ ],
590
+ "mode": "background_when_host_supports_subagents",
591
+ "fallback": "if no real background branch can start, say the real sequence and do not claim background drafting is running",
592
+ "toolCallRequiredInBranch": "get_subskill_prompt({ subskillName: \"generate-messages\", offset, limit }) until hasMore=false",
593
+ "runtimeProofTransport": "CampaignOffer.watchNarration.workerDetails.messageDraftBuilder",
594
+ "purpose": "start the provisional message draft from the imported review batch immediately; do not defer this to filter approval"
583
595
  }
584
596
  ],
585
597
  "requiredCampaignState": [
@@ -702,7 +714,7 @@
702
714
  "purpose": "load canonical post-lead worker names"
703
715
  },
704
716
  {
705
- "action": "launch_or_reuse_post_lead_workstreams",
717
+ "action": "launch_or_reuse_lead_fit_builder_and_existing_message_draft",
706
718
  "mode": "parallel_when_host_supports_subagents",
707
719
  "inputs": [
708
720
  "campaignId",
@@ -713,7 +725,8 @@
713
725
  "filterChoice"
714
726
  ],
715
727
  "stateSource": "CampaignOffer and workflow table rows",
716
- "debugFilesOptionalOnly": true
728
+ "debugFilesOptionalOnly": true,
729
+ "messageDraftRule": "reuse or join the Message Draft Builder branch that started immediately after confirm_lead_list; do not start first-time message drafting here unless the earlier branch failed to start"
717
730
  },
718
731
  {
719
732
  "action": "save_filter_rubrics_to_campaign",
@@ -727,7 +740,7 @@
727
740
  "requiredSideEffects": {
728
741
  "enableICPFilters": true,
729
742
  "currentStep": "apply-icp-rubric",
730
- "watchNarration.headline": "Filter Leads is ready"
743
+ "watchNarration.headline": "Filter rules saved"
731
744
  }
732
745
  }
733
746
  ],
@@ -769,7 +782,8 @@
769
782
  ],
770
783
  "hardRules": [
771
784
  "after_save_rubrics_currentStep_must_be_apply-icp-rubric",
772
- "do_not_move_browser_to_messages_until_filter_leads_step_is_current_or_filters_are_explicitly_skipped"
785
+ "do_not_move_browser_to_messages_until_filter_leads_step_is_current_or_filters_are_explicitly_skipped",
786
+ "message_draft_builder_start_is_not_deferred_until_filters"
773
787
  ],
774
788
  "transitions": {
775
789
  "post_lead_workstreams_ready": "message-review",
@@ -800,7 +814,7 @@
800
814
  "requiredSideEffects": {
801
815
  "enableICPFilters": true,
802
816
  "currentStep": "apply-icp-rubric",
803
- "watchNarration.headline": "Filter Leads is ready"
817
+ "watchNarration.headline": "Filter rules saved"
804
818
  }
805
819
  }
806
820
  ],
@@ -968,17 +982,26 @@
968
982
  "revise_messaging"
969
983
  ],
970
984
  "transitions": {
971
- "message_approved": "auto-execute-messaging",
985
+ "message_approved": "validate-sample",
972
986
  "revise_messaging": "message-generation"
973
987
  }
974
988
  },
975
989
  {
976
990
  "id": "validate-sample",
977
- "label": "Validate bounded review batch (legacy)",
978
- "currentStepValue": "validate-sample",
979
- "legacyOnly": true,
991
+ "label": "Validate bounded review batch",
992
+ "currentStepValue": "apply-icp-rubric",
980
993
  "reference": "references/sample-validation-loop.md",
994
+ "visibleStepRule": "This is the same Filter Leads screen reached by save_rubrics. Do not route away from or back to Filter Leads on approve-message; save the approved template, refresh watch narration on apply-icp-rubric, then queue the bounded Enrich Prospect cells.",
981
995
  "onEnter": [
996
+ {
997
+ "tool": "update_campaign",
998
+ "requiredValues": {
999
+ "currentStep": "apply-icp-rubric",
1000
+ "watchNarration.stage": "fit-message"
1001
+ },
1002
+ "purpose": "keep the watched UI on Filter Leads while the approved template starts the bounded cascade",
1003
+ "watchNarrationRule": "Say the template is saved and Filter Leads is now running the bounded enrichment and scoring pass."
1004
+ },
982
1005
  {
983
1006
  "tool": "queue_cells",
984
1007
  "purpose": "queue ICP/enrichment cells for the bounded review batch only",
@@ -1121,10 +1144,21 @@
1121
1144
  {
1122
1145
  "tool": "update_campaign",
1123
1146
  "requiredValues": {
1124
- "currentStep": "awaiting-user-greenlight",
1147
+ "currentStep": "auto-execute-messaging",
1125
1148
  "watchNarration.stage": "review-ready"
1126
1149
  },
1127
- "watchNarrationRule": "Say what just happened, that review-batch messages are ready, and that the next action is Settings/sender review."
1150
+ "watchNarrationRule": "Say what just happened, that review-batch messages are ready in Messages, and that the next action is reviewing or approving generated messages before Settings."
1151
+ },
1152
+ {
1153
+ "action": "ask_generated_message_review_choice",
1154
+ "uses": "request_user_input",
1155
+ "choices": [
1156
+ "Approve generated messages",
1157
+ "Revise filters",
1158
+ "Revise message template",
1159
+ "Pause here"
1160
+ ],
1161
+ "rule": "Do not advance to Settings until the generated review-batch messages have been reviewed and approved."
1128
1162
  }
1129
1163
  ],
1130
1164
  "allowedTools": [
@@ -1151,11 +1185,13 @@
1151
1185
  "proposed_token_never_persisted_in_rewrite"
1152
1186
  ],
1153
1187
  "waitFor": [
1154
- "review_batch_ready",
1188
+ "generated_messages_approved",
1155
1189
  "sample_revision_required"
1156
1190
  ],
1157
1191
  "transitions": {
1158
- "review_batch_ready": "awaiting-user-greenlight",
1192
+ "generated_messages_approved": "awaiting-user-greenlight",
1193
+ "revise_filters": "filter-rubric",
1194
+ "revise_messaging": "message-generation",
1159
1195
  "escalation_triggered": "escalation"
1160
1196
  }
1161
1197
  },
@@ -1188,7 +1224,7 @@
1188
1224
  "connect or select a LinkedIn sender",
1189
1225
  "Slack reply review",
1190
1226
  "recommended sequence",
1191
- "nothing starts until the user confirms launch"
1227
+ "final launch confirmation is still ahead"
1192
1228
  ]
1193
1229
  },
1194
1230
  {
@@ -3,17 +3,15 @@
3
3
  This policy is the invariant layer for the from-scratch v2 orchestrator. Follow
4
4
  it even if prompt prose is ambiguous.
5
5
 
6
- ## 1) JSON State Machine First
6
+ ## 1) Campaign State First
7
7
 
8
- `core/flow.v2.json` is the source of truth for:
8
+ `core/flow.v2.json` defines the stage order and tool gates. CampaignOffer state,
9
+ the watched app, selected source/list state, and campaign-table rows are the
10
+ runtime source of truth.
9
11
 
10
- - stage order
11
- - required artifacts
12
- - produced artifacts
13
- - allowed tools
14
- - forbidden tools
15
- - wait events
16
- - transitions
12
+ Normal create-campaign-v2 runs do not use local markdown/json artifacts as
13
+ required state. Debug artifacts can exist only for explicit debug/UAT or legacy
14
+ validation harnesses, and they must never override live campaign state.
17
15
 
18
16
  `SKILL.md` explains how to execute the flow. It does not replace the flow.
19
17
 
@@ -28,40 +26,37 @@ bootstrap -> brief-interview
28
26
  Do not start at `validate-artifacts` unless resuming a compatibility run where
29
27
  the complete upstream artifact set already exists.
30
28
 
31
- ## 3) No Mutation Before Approval
29
+ ## 3) Shell-First Mutation Gates
32
30
 
33
- Before the user explicitly chooses `approve` at the commit gate, do not call:
31
+ Create the campaign shell early after campaign identity and the initial brief
32
+ are good enough for the customer to watch setup progress. Then enforce these
33
+ mutation gates:
34
34
 
35
- - `create_campaign`
36
- - `save_rubrics`
37
- - `import_leads`
38
- - `confirm_lead_list`
39
- - `update_campaign`
40
- - `queue_cells`
41
- - `start_campaign`
35
+ - Do not call provider search/import tools until the user approves the source
36
+ plan or explicitly chooses a source.
37
+ - Do not call `import_leads` or `confirm_lead_list` until the concrete source
38
+ action is approved.
39
+ - Import/confirm only the first bounded review batch before message approval.
40
+ - Do not call `queue_cells` until filter choice is resolved, rubrics are saved
41
+ when filters are enabled, and the default Use Template path has an approved
42
+ message template/token rule set.
43
+ - Do not attach a sequence or call `start_campaign` until the user explicitly
44
+ chooses to launch.
42
45
 
43
46
  Customer roleplay critique is advisory only. It cannot approve a campaign.
44
47
 
45
- ## 4) Artifact Gates
48
+ ## 4) State Gates
46
49
 
47
- Do not run a downstream stage until the active step's `requiredArtifacts` exist.
48
- Intermediate user-review gates are interrupt-only: auto-continue when an
49
- artifact is confirmed and no strategic tradeoff is present. The final commit
50
- gate is the only mandatory pre-mint approval gate.
50
+ Do not run a downstream stage until the matching live state exists:
51
51
 
52
- The minimum pre-approval chain is:
53
-
54
- ```text
55
- brief.md
56
- lead-review.md
57
- lead-sample.json
58
- lead-filter.md
59
- message-prep.md (optional)
60
- message-candidate-drafts.md (optional, generated from find-leads basis rows)
61
- message-validation.md
62
- approval-packet.md
63
- commit-gate-decision.md
64
- ```
52
+ - campaign shell exists before a watch link is shown as active
53
+ - selected source/list state exists before importing a review batch
54
+ - `workflowTableId` and non-empty bounded review-batch rows exist before filter
55
+ and message branches run
56
+ - `leadScoringRubrics` are saved before queueing ICP filter cells when filters
57
+ are enabled
58
+ - approved message template/token rules are written to campaign brief before
59
+ queueing Generate Message cells on the default Use Template path
65
60
 
66
61
  ## 5) Revision Routing
67
62
 
@@ -73,10 +68,11 @@ Revision choices route back to the exact upstream stage:
73
68
  - `revise-messaging` -> `message-generation`
74
69
  - `abort` -> stop with zero DB mutation
75
70
 
76
- ## 6) Post-Approval Tail
71
+ ## 6) Post-Message Tail
77
72
 
78
- After `approve`, mint atomically with `create_campaign` and `save_rubrics`.
79
- Only then surface the watch link and continue the cascade-driven tail.
73
+ After message approval, queue only the bounded review-batch cells needed to move
74
+ the watched app through enrichment, ICP filtering, and approved-template
75
+ message generation. Keep the tail observable through watch narration.
80
76
 
81
77
  The tail stops at `awaiting-user-greenlight`. Never call `start_campaign`
82
78
  inside the autonomous tail.