@sellable/mcp 0.1.143 → 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.
@@ -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:
@@ -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
@@ -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.
@@ -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,14 +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
- source output plus a non-empty bounded review batch. The join gate is live
266
- branch readiness: saved rubrics or a resolved skip-filter choice, plus a message
267
- recommendation grounded in the same campaign/table basis.
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.
268
276
 
269
277
  Only promise parallel post-lead work when parallel work actually started. If the
270
278
  host cannot or should not launch background branches, say the real sequence:
@@ -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
  {
@@ -33,8 +33,8 @@ order (all before waiting for the user):
33
33
  `get_campaign_navigation_state` when available so the watch link visibly
34
34
  lands on Settings before sender setup.
35
35
  4. Explain sender setup and Slack in normal customer language: Sellable needs a
36
- connected LinkedIn sender before anything can send, and Slack reply review
37
- matters because replies and approvals need a channel the team will monitor.
36
+ connected LinkedIn sender for launch, and Slack reply review matters because
37
+ replies and approvals need a channel the team will monitor.
38
38
  5. If no connected sender exists, surface the campaign Settings link
39
39
  `/campaign-builder/{campaignId}/settings?mode=claude`, tell the user to
40
40
  connect a sender there, and STOP. Do not attach sequence and do not start.
@@ -70,7 +70,7 @@ The final handoff must answer five customer questions in plain language:
70
70
  - why the selected LinkedIn sender and Slack reply review matter before launch
71
71
  - what clicking Start does (approves/starts the campaign send path)
72
72
  - how to revise (reply with what to change, or use the campaign UI)
73
- - whether anything has started yet (nothing sends until the user starts)
73
+ - current launch status and what the final Start action does
74
74
 
75
75
  When `lead-source-intake.json` exists, also answer:
76
76
 
@@ -84,8 +84,8 @@ When `lead-source-intake.json` exists, also answer:
84
84
 
85
85
  Use the exact state name `awaiting-user-greenlight` so logs and UX artifacts
86
86
  can verify the state-machine stop point, but explain it in normal words: the
87
- campaign is built, sender/sequence setup is being completed, and nothing sends
88
- until the user's final start decision. The watched UI may advance through
87
+ campaign is built, sender/sequence setup is being completed, and the final
88
+ start decision is still ahead. The watched UI may advance through
89
89
  Settings, Sequence, and Send while this state-machine step remains the final
90
90
  handoff.
91
91
 
@@ -91,19 +91,94 @@ but the [topic] thread felt close enough to send`. Otherwise omit the
91
91
 
92
92
  ## Customer-Facing Message Review
93
93
 
94
- Render this in chat before asking:
95
-
96
- - `Status: message-review`
97
- - `Subject:`
98
- - `Message:` with the tokenized template or approved AI-native message
99
- - `Rendered examples:`
100
- - `Good token fill:`
101
- - `Good omit:`
102
- - `Token notes:`
103
- - `My take:`
104
- - `Suggested adjustment:`
105
- - `Question: approve-message or revise-messaging?`
106
- - `Recommendation: approve-message` or `Recommendation: revise-messaging`
94
+ Render this in chat before asking. Use Markdown structure so the approval target
95
+ is visually scannable:
96
+
97
+ ````markdown
98
+ Status: message-review
99
+
100
+ ## Message Template
101
+
102
+ **Subject**
103
+
104
+ ```text
105
+ {{tokenized_subject}}
106
+ ```
107
+
108
+ **Body**
109
+
110
+ ```text
111
+ {{tokenized_message_body}}
112
+ ```
113
+
114
+ ## Rendered Examples
115
+
116
+ ### Good token fill
117
+
118
+ Use when the row has a clean, supported fill.
119
+
120
+ ```text
121
+ Subject: ...
122
+
123
+ Hey First,
124
+
125
+ ...
126
+ ```
127
+
128
+ ### Good omit / fallback
129
+
130
+ Use when a row signal or company context is missing, weak, or awkward.
131
+
132
+ ```text
133
+ Subject: ...
134
+
135
+ Hey First,
136
+
137
+ ...
138
+ ```
139
+
140
+ ### Bad fill to avoid
141
+
142
+ ```text
143
+ Subject: ...
144
+
145
+ Hey First,
146
+
147
+ ...
148
+ ```
149
+
150
+ **Why this is wrong:** one sentence naming the exact token-fill failure.
151
+
152
+ ## Token Notes
153
+
154
+ | Token | Use when | Fallback |
155
+ | ---------------- | ------------------------ | -------- |
156
+ | `{{first_name}}` | Clean first name exists. | `there` |
157
+
158
+ ## Recommendation
159
+
160
+ **My take:** ...
161
+
162
+ **Suggested adjustment:** ...
163
+
164
+ **Question:** approve-message or revise-messaging?
165
+
166
+ **Recommendation:** approve-message
167
+ ````
168
+
169
+ Formatting requirements:
170
+
171
+ - Put the tokenized template and every rendered example in fenced `text` blocks
172
+ so chat gives them a distinct background.
173
+ - `Good token fill` and `Good omit / fallback` must each contain a complete
174
+ rendered subject + body, not a bullet list of token names or a single
175
+ bridge-line fragment.
176
+ - Include `Bad fill to avoid` when the row sample has a tempting but unsafe
177
+ source-mechanics or raw-headline fill; otherwise include `Bad fill to avoid:
178
+ none found`.
179
+ - Use a token notes table, not paragraph-only token notes.
180
+ - Keep reasoning outside the code blocks so the blocks are easy to inspect and
181
+ approve.
107
182
 
108
183
  `My take` and `Suggested adjustment` must be specific. The adjustment can be
109
184
  "approve as-is, or revise once to X if you want Y"; it must not be empty.
@@ -20,7 +20,9 @@ auto-revise leads.
20
20
 
21
21
  ## Inputs
22
22
 
23
- - `CampaignOffer.currentStep === "validate-sample"` (set at end of Step 13)
23
+ - `CampaignOffer.currentStep === "apply-icp-rubric"` (the watched app is
24
+ already on Filter Leads after `save_rubrics`; `validate-sample` is the
25
+ logical loop name, not a visible route)
24
26
  - Imported review batch from Step 13 (size: `importLimit`, default 15)
25
27
  - Config from `auto-execute.yaml`: `sample.sampleSize`,
26
28
  `sample.minProjectedPass`, `sample.maxRevisionRounds`
@@ -48,7 +50,8 @@ auto-revise leads.
48
50
  the enrichment batch ids; NOT by calling wait_for_rubric_results
49
51
  before rubric was scheduled)
50
52
 
51
- 5. check_rubric(sample)
53
+ 5. do not call `check_rubric`; the product cascade runs enrichment and rubric
54
+ scoring from the queued Enrich Prospect cells
52
55
 
53
56
  6. wait_for_rubric_results(sample, targetCount = <cohortSize>, minPassedCount = 1)
54
57
  - cohortSize = stats.totalRows of the enrichment batch, or the
@@ -2,8 +2,7 @@
2
2
 
3
3
  This reference governs Step 15 (`auto-execute-messaging`) re-cascade
4
4
  behavior when Step 14's validate-sample loop graduates additional rows
5
- from pending → passed after the first `generate_messages` call has
6
- already run.
5
+ from pending → passed after the first Generate Message cells have already run.
7
6
 
8
7
  Load whenever Step 15 is about to transition to
9
8
  `awaiting-user-greenlight`, and on every resume into Step 15.
@@ -25,7 +24,7 @@ Re-cascade runs whenever ALL of the following are true:
25
24
 
26
25
  1. Step 15 has already observed the initial review-batch message cascade.
27
26
  2. A subsequent check of rubric state shows rows that were pending at
28
- first generate_messages time are now passed.
27
+ first message-generation pass are now passed.
29
28
  3. Those newly-passed rows do NOT yet have generated messages
30
29
  (`messagesCount` flat relative to pre-cascade).
31
30
  4. Step 15 has NOT yet transitioned to `awaiting-user-greenlight`.