@sellable/mcp 0.1.130 → 0.1.132

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.130",
3
+ "version": "0.1.132",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -482,7 +482,7 @@ until you approve the source.`
482
482
  `Lead source is set. I'll import the first 15-row review batch into the
483
483
  campaign table, then ask you to Choose filters or skip. I may let the Message
484
484
  Draft Builder prepare a template in the background, but template review waits
485
- until the filter choice is resolved and you choose Use Template.`
485
+ until the filter choice is resolved and the template is ready for approval.`
486
486
  - During long post-intake work, show concise progress checkpoints before the
487
487
  next expensive stage: source being checked, source switch/tradeoff if any,
488
488
  lead sample usable, filter/message drafting, and message-review rule loading.
@@ -525,18 +525,19 @@ until the filter choice is resolved and you choose Use Template.`
525
525
  and cannot override `lead-filter.md`.
526
526
  - `message-validation.md` is the internal validation artifact produced by the
527
527
  Message Draft Builder / `message generation` stage. It is provisional until
528
- the user answers filter choice and then chooses Use Template in Messages.
528
+ the user answers filter choice and approves the message template in chat.
529
529
  - `message-review.md` and `message-review-decision.md` are the mandatory
530
530
  message quality gate outputs between `message-validation.md` and
531
531
  `approval-packet.md`.
532
532
  - Run the dependency chain as a DAG: `create-campaign-brief` -> `find leads` ->
533
533
  bounded import/confirm. Once the source decision, lead sample, and campaign
534
- table `workflowTableId` exist, the normal path is the `filter-choice` user
535
- gate. If the user chooses filters, `post-lead-workstreams` launches filter
536
- leads and can let the Message Draft Builder run from the same basis (live
537
- campaign brief, source decision, lead sample, and the imported review-batch
538
- rows) as separate workstreams when the host exposes the named Sellable
539
- post-find-leads agents or real background work.
534
+ table `workflowTableId` exist, immediately start the Message Draft Builder
535
+ from the live campaign brief, approved source, source list, and imported
536
+ review-batch rows before telling the user it is in progress. The normal path
537
+ then reaches the `filter-choice` user gate. If the user chooses filters,
538
+ `post-lead-workstreams` launches filter leads and reuses the in-flight Message
539
+ Draft Builder work from the same basis as separate workstreams when the host
540
+ exposes the named Sellable post-find-leads agents or real background work.
540
541
  First call `get_post_find_leads_scout_registry` and use the returned
541
542
  canonical `name` values only when those names are available in the current
542
543
  runtime. In Claude Code, use both returned Task/Agent subagents in the same
@@ -548,18 +549,20 @@ until the filter choice is resolved and you choose Use Template.`
548
549
  `filter-rubric` and `message-generation` steps remain focused retry and
549
550
  resume targets.
550
551
  - Message generation does not need `lead-filter.md` to start, but it is only
551
- background template drafting until the user reaches Messages. The moment the
552
- bounded review batch is imported, `workflowTableId` is ready, and the user is
553
- on/after filter choice, the Message Draft Builder may start from the live
554
- campaign brief, source decision, lead sample, and imported campaign table
555
- sample. It can prepare proof inventory, token strategy, and candidate angles
556
- while filter-leads tightens keep/exclude rules. Template review cannot start
557
- until filter choice is answered and the user chooses Use Template. If filters
558
- are enabled, template review is locked until rubrics are saved, a bounded
559
- filter run has usable passing/probably passing rows, and the draft reconciles
560
- to those rows. Prefer at least 2 usable passing rows; if only 1 passes, show
561
- weak-sample copy and ask whether to continue, revise, import more, or skip
562
- filters.
552
+ background template drafting until the user approves the template. The moment
553
+ the bounded review batch is imported, `workflowTableId` is ready, and
554
+ `get_rows_minimal` proves rows exist, the Message Draft Builder must start
555
+ from the live campaign brief, source decision, lead sample, and imported
556
+ campaign table sample. Do not show `Message Draft Builder: In Progress` unless
557
+ the worker or parent-thread fallback has actually started. It can prepare
558
+ proof inventory, token strategy, and candidate angles while filter-leads
559
+ tightens keep/exclude rules. Template review cannot start
560
+ until filter choice is answered and rubrics are saved. If filters are enabled,
561
+ the watched browser stays on Filter Leads while the template is approved in
562
+ chat. After approval is saved to the campaign brief, queue the bounded
563
+ enrichment/filter run and prefer at least 2 usable passing rows before moving
564
+ to Messages. If only 1 passes, show weak-sample copy and ask whether to
565
+ continue, revise, import more, or skip filters.
563
566
  If a legacy/resume host starts message prep from preview rows before import,
564
567
  it still needs at least 3 probable good-fit rows and must reconcile the final
565
568
  winner against the imported review batch before message review.
@@ -590,13 +593,18 @@ until the filter choice is resolved and you choose Use Template.`
590
593
  `currentStep` before waiting on source-scout results, so relevant search tabs
591
594
  appear in real time.
592
595
  - For post-lead workstreams, first call
593
- `get_post_find_leads_scout_registry` and launch exactly the returned
594
- `filter-leads` and `message-generation` scouts when real subagents are
595
- available. This is the two Task/Agent subagents path for the
596
- `post-lead-workstreams` step. This is the same registry pattern as source scouting, but the
597
- trigger is source approval and the join gate is both `lead-filter.md` and
598
- `message-validation.md` existing from the same live campaign brief/source
599
- decision/lead-sample basis.
596
+ `get_post_find_leads_scout_registry` after the review batch import confirms
597
+ rows. Launch the returned `message-generation` scout immediately, before the
598
+ filter-choice/watch copy says message work is running. When the user chooses
599
+ filters, launch the returned `filter-leads` scout and reuse the in-flight
600
+ message branch. This is the Task/Agent subagents path for the
601
+ `post-lead-workstreams` step. This is the same registry pattern as source
602
+ scouting, but the trigger is bounded review-batch import and the join gate is
603
+ both `lead-filter.md` and `message-validation.md` existing from the same live
604
+ campaign brief/source decision/imported review-batch basis. When the host can
605
+ launch both branches together, this is still the two Task/Agent subagents
606
+ path; otherwise message-generation starts first and filter-leads joins after
607
+ the filter choice.
600
608
  - Never run a downstream stage until the active `flow.v2.json` step's required
601
609
  campaign state and required normal inputs exist. In normal customer runs, do
602
610
  not create optional debug artifacts just to satisfy a file gate.
@@ -630,18 +638,19 @@ batch`, and a no-launch safety note. Do not leave the guide saying
630
638
  waiting for message work to finish. Persist `currentStep:
631
639
  "apply-icp-rubric"` and `watchNarration.stage: "fit-message"`, then read the
632
640
  bounded review batch with `get_rows_minimal`, but do not queue workflow cells
633
- yet. Tell the user the fit rules are saved, the message template needs
634
- approval next, and enrichment/filtering will start after approval. Do not call
635
- `check_rubric` in the normal create-campaign-v2 path. Use Template is the
636
- default message path. AI Generated is an explicit opt-out that cancels or
637
- ignores the background template draft and must not let late template output
638
- overwrite campaign state. Product Generate Message cells should not run from
639
- the background template path until template/token rules are approved. After
640
- message approval, update the campaign brief with an Approved Message Template
641
- containing `{{...}}` tokens and keep `enableICPFilters: true`; then queue only
641
+ yet. Tell the user the fit rules are saved, the message template is being
642
+ finalized for approval, and enrichment/filtering will start only after that
643
+ approval is saved into the campaign brief. Do not call `check_rubric` in the
644
+ normal create-campaign-v2 path. Do not ask Use Template vs AI Generated in
645
+ normal runs; the Message Draft Builder template path is the default and only
646
+ normal path. Product Generate Message cells should not run from the background
647
+ template path until template/token rules are approved. After message approval,
648
+ update the campaign brief with an Approved Message Template containing
649
+ `{{...}}` tokens and keep `enableICPFilters: true`; then queue only
642
650
  pending/error `enrichCellId` values with `queue_cells` to start enrichment and
643
- filtering. Generate Message detects template mode from those tokens, not from
644
- `useMessagingTemplate`.
651
+ filtering. Once a couple review rows pass, move to Messages so Generate
652
+ Message can run from the approved template. Generate Message detects template
653
+ mode from those tokens, not from `useMessagingTemplate`.
645
654
  - During pre-import validation, do not call `check_rubric`; use the lead-filter
646
655
  artifacts and only use campaign-backed scoring after Step 13 imports the
647
656
  15-lead test batch.
@@ -697,11 +706,8 @@ There are six customer-visible gates in the net-new hosted flow:
697
706
  compressing the source decision into message review.
698
707
  - `filter-choice` asks whether to use filters or skip after the non-empty
699
708
  review batch is imported. This is the first post-import user gate.
700
- - `messages-mode-choice` asks whether to Use Template or choose AI Generated.
701
- Use Template is recommended. AI Generated is an explicit opt-out that cancels
702
- or ignores the background template draft.
703
- - `message-review` is the mandatory template quality gate only when the user
704
- chooses Use Template. It asks only whether to proceed with the selected
709
+ - `message-review` is the mandatory template quality gate. It asks only whether
710
+ to proceed with the selected
705
711
  message (`approve-message`) or run one more messaging revision
706
712
  (`revise-messaging`). `approve-message` authorizes syncing the approved
707
713
  template/token rules into the campaign brief and queueing/observing the
@@ -1124,7 +1130,10 @@ and matching `currentStep` before `lookup_sales_nav_filter`,
1124
1130
  `confirm_lead_list`. For example, if the user approves Sales Nav while the
1125
1131
  browser is still showing Signal Discovery, set `leadSourceProvider: "sales-nav"`
1126
1132
  and `currentStep: "sales-nav"` first so the browser switches to the Sales Nav
1127
- lane and the user can watch the approved source progress.
1133
+ lane and the user can watch the approved source progress. Do not set
1134
+ `currentStep: "confirm-lead-list"` before `import_leads` returns the lead-list
1135
+ table/job id; `import_leads` moves there after the provider import API starts so
1136
+ the import page has progress state when it appears.
1128
1137
 
1129
1138
  If you ask for lead-source approval, the question and choices must name the
1130
1139
  source decision. Prefer `Approve Sales Nav with founder/CEO filters, or use
@@ -1294,27 +1303,24 @@ long prompt plus safety gate cannot safely approve the draft, stop at
1294
1303
  `revise-messaging` with the exact failure.
1295
1304
 
1296
1305
  Do NOT proceed to Step 4 (message review gate) unless the user has answered
1297
- filter choice, the Messages step has shown the mode choice, the user chose Use
1298
- Template, and `message-validation.md` contains the safety-gate required
1306
+ filter choice, the watched app is still on Filter Leads while approval is
1307
+ pending, and `message-validation.md` contains the safety-gate required
1299
1308
  sections, a raw sendable Selected Winner, and an explicit single-first-send
1300
- PASS. If the user reaches Messages and chose Use Template before the draft is
1301
- ready, say you are waiting for the Message Draft Builder and do not ask for
1302
- approval. If the draft worker fails, produces no usable message, or has no known
1303
- worker status, require retry/regenerate copy instead of approval copy. If
1309
+ PASS. If the draft is not ready, say you are waiting for the Message Draft
1310
+ Builder and do not ask for approval. If the draft worker fails, produces no
1311
+ usable message, or has no known worker status, require retry/regenerate copy
1312
+ instead of approval copy. If
1304
1313
  `message-validation.md` contains post-accept DM, follow-up, second-touch,
1305
1314
  cadence, branch, or other sequence-shaped copy, do not summarize it as ready;
1306
1315
  route back to message-generation and require a single first outbound send.
1307
1316
 
1308
- Messages first shows mode choice:
1309
-
1310
- 1. Use Template (recommended): wait for and review the Message Draft Builder
1311
- template. If filters are enabled, lock this review until saved rubrics and a
1312
- bounded filter run produce usable passing/probably passing rows. Prefer at
1313
- least 2 usable passing rows; if only 1 passes, use weak-sample copy and ask
1314
- whether to continue, revise, import more, or skip filters.
1315
- 2. AI Generated: this is an explicit opt-out. Cancel or ignore the background
1316
- template draft and prevent late template output from overwriting campaign
1317
- state.
1317
+ There is no normal Use Template vs AI Generated mode question. After rubrics are
1318
+ saved, stay on Filter Leads, wait for and review the Message Draft Builder
1319
+ template, approve/revise it in chat, then write the approved template into the
1320
+ campaign brief. Only then queue enrichment/ICP scoring for the bounded review
1321
+ batch. Prefer at least 2 usable passing rows before moving the watched browser
1322
+ to Messages; if only 1 passes, use weak-sample copy and ask whether to continue,
1323
+ revise, import more, or skip filters.
1318
1324
 
1319
1325
  Product Generate Message cells should not run from the background template path
1320
1326
  until template/token rules are approved.
@@ -920,7 +920,8 @@
920
920
  {
921
921
  "id": "auto-execute-leads",
922
922
  "label": "Step 13: Confirm source and import 15 lead review batch",
923
- "currentStepValue": "confirm-lead-list",
923
+ "currentStepValue": null,
924
+ "visibleStepTiming": "Do not move the watched UI to confirm-lead-list on Step 13 entry. Keep currentStep on the approved provider/source lane while import_leads starts. The import_leads tool owns setting currentStep to confirm-lead-list after the provider import API returns a leadListId/jobId, so the user lands on the import page with a table/progress state already available.",
924
925
  "reference": "references/step-13-import-leads.md",
925
926
  "onEnter": [
926
927
  {
@@ -951,10 +952,11 @@
951
952
  },
952
953
  {
953
954
  "action": "watch_mode_orient",
954
- "watchNarrationRule": "Before import_leads or confirm_lead_list starts, align the guide with chat by setting review-batch watchNarration to current-tense source materialization copy. Also persist the approved source provider/currentStep first: Sales Nav approval must set leadSourceProvider `sales-nav` and currentStep `sales-nav`, Signals approval must set `signal-discovery`, and Prospeo approval must set `prospeo`. Use a headline like `Preparing the source list`; explain that the browser is on the approved source lane while Codex materializes only the approved source-capacity plan, then imports only the bounded 15-row review batch into the campaign table; include a no-launch safety note."
955
+ "watchNarrationRule": "Before import_leads starts, align the guide with chat by setting review-batch watchNarration to current-tense source materialization copy while keeping currentStep on the approved source lane. Also persist the approved source provider/currentStep first: Sales Nav approval must set leadSourceProvider `sales-nav` and currentStep `sales-nav`, Signals approval must set `signal-discovery`, and Prospeo approval must set `prospeo`. Do not set currentStep to `confirm-lead-list` before import_leads returns a leadListId/jobId; import_leads owns that move after the provider import API call so the import page has progress state when it appears. Use a headline like `Preparing the source list`; explain that the browser is on the approved source lane while Codex materializes only the approved source-capacity plan, then imports only the bounded 15-row review batch into the campaign table; include a no-launch safety note."
955
956
  },
956
957
  {
957
958
  "tool": "import_leads",
959
+ "currentStepTiming": "Omit currentStep or pass `confirm-lead-list`; either way the tool must start the provider import API first, then update CampaignOffer.selectedLeadListId/currentStep after it has a leadListId/jobId. Never navigate the watched UI to confirm-lead-list with no import job/table to show.",
958
960
  "sameTurnPreflight": "Immediately before import_leads, call get_provider_prompt({ provider, campaignOfferId }) in the same resumed turn, even if source discovery loaded the provider prompt earlier.",
959
961
  "requiredFields": [
960
962
  "campaignOfferId",
@@ -1029,6 +1031,44 @@
1029
1031
  ],
1030
1032
  "rule": "If confirm_lead_list succeeds but get_rows_minimal returns zero imported review-batch rows, do not advance to filter-choice. Keep the user in source/import recovery and ask for retry import, import more from the approved source, or revise source."
1031
1033
  },
1034
+ {
1035
+ "tool": "get_post_find_leads_scout_registry",
1036
+ "purpose": "load_post_import_message_draft_builder_registry",
1037
+ "requiredBeforeMessageDraftLaunch": true
1038
+ },
1039
+ {
1040
+ "action": "launch_message_draft_builder_after_review_batch_import",
1041
+ "mode": "background_required_when_host_supports_subagents",
1042
+ "registryRequired": "get_post_find_leads_scout_registry",
1043
+ "branch": {
1044
+ "name": "message-generation",
1045
+ "target": "generate-messages",
1046
+ "workerName": "post-find-leads-message-scout",
1047
+ "inputs": [
1048
+ "campaignBrief",
1049
+ "selected source decision",
1050
+ "selectedLeadListId source list",
1051
+ "workflowTableId imported 15-row review batch"
1052
+ ],
1053
+ "toolCallRequiredBeforeArtifacts": [
1054
+ "get_subskill_prompt({ subskillName: \"generate-messages\" }) until hasMore=false"
1055
+ ],
1056
+ "producesArtifacts": [
1057
+ "template recommendation",
1058
+ "token fill rules",
1059
+ "rendered sample"
1060
+ ],
1061
+ "optionalProducesArtifacts": [
1062
+ "message-validation.md",
1063
+ "message-prep.md",
1064
+ "message-candidate-drafts.md"
1065
+ ],
1066
+ "ownership": "proof inventory, token strategy, angle drafting, skeptical-prospect review, and selected winner only"
1067
+ },
1068
+ "requiredBeforeFilterChoiceWatchCopy": true,
1069
+ "rule": "Immediately after get_rows_minimal proves the bounded review batch is non-empty, start the Message Draft Builder from the live campaign brief, approved source, selectedLeadListId, and imported workflowTableId rows. Do this before the watched campaign moves to filter-choice or Filter Rules so any guide copy saying Message Draft Builder is In Progress is true.",
1070
+ "fallback": "If the host cannot launch the post-find-leads-message-scout in the background, load the full generate-messages prompt in the parent thread and start the message-generation work before reporting Message Draft Builder as In Progress. If message work cannot start, do not show running copy; surface pending/blocked template-start copy instead."
1071
+ },
1032
1072
  {
1033
1073
  "tool": "update_campaign",
1034
1074
  "requiredFields": [
@@ -1039,9 +1079,10 @@
1039
1079
  "requiredValues": {
1040
1080
  "currentStep": "filter-choice",
1041
1081
  "watchNarration.stage": "fit-message",
1042
- "watchNarration.headline": "Added to Campaign"
1082
+ "watchNarration.headline": "Added to Campaign",
1083
+ "watchNarration.workerStatuses.messageDraftBuilder": "running_after_launch_message_draft_builder_after_review_batch_import_only"
1043
1084
  },
1044
- "watchNarrationRule": "After the bounded review batch is present and non-empty, update the watched guide to `Added to Campaign` and ask the user to Choose filters or skip. This is filter intent only: do not say filtering the batch before rubrics are saved. The Message Draft Builder may start in the background, but template review is locked until the filter path is reconciled and the user later chooses Use Template. Do not set enableICPFilters=true until save_rubrics succeeds with active criteria. Nothing enriches, validates, or sends until the user approves the message mode and template/token rules where applicable."
1085
+ "watchNarrationRule": "After the bounded review batch is present and non-empty, and after launch_message_draft_builder_after_review_batch_import has actually started or resumed message-generation, update the watched guide to `Added to Campaign` and ask the user to Choose filters or skip. This is filter intent only: do not say filtering the batch before rubrics and message approval are saved. The Message Draft Builder should be reported as In Progress only if the worker or parent-thread fallback has actually started. No enrichment, filtering, Generate Message cells, sequence, or sending starts until the message template is approved and saved to the campaign brief. Do not set enableICPFilters=true until save_rubrics succeeds with active criteria."
1045
1086
  }
1046
1087
  ],
1047
1088
  "allowedTools": [
@@ -1057,7 +1098,11 @@
1057
1098
  "load_csv_linkedin_leads",
1058
1099
  "load_csv_domains",
1059
1100
  "get_provider_prompt",
1060
- "get_campaign"
1101
+ "get_campaign",
1102
+ "get_post_find_leads_scout_registry",
1103
+ "get_subskill_prompt",
1104
+ "Task",
1105
+ "spawn_agent"
1061
1106
  ],
1062
1107
  "doNotAllow": [
1063
1108
  "queue_cells",
@@ -1089,10 +1134,10 @@
1089
1134
  "requiredVisibleContent": [
1090
1135
  "Choose filters or skip",
1091
1136
  "Use filters to keep only qualified leads",
1092
- "Skip filters and continue to Messages",
1093
- "active filtering starts only after rubrics are saved"
1137
+ "Skip filters and continue to message template review",
1138
+ "active filtering starts only after rubrics and the approved message template are saved"
1094
1139
  ],
1095
- "chatRenderRule": "The first post-import user gate is filter choice. Ask the user to Choose filters or skip. Make clear that active filtering starts only after rubrics are saved; do not say filtering the batch before rubrics are saved. If the user skips filters, go to Messages mode choice once the review batch is ready."
1140
+ "chatRenderRule": "The first post-import user gate is filter choice. Ask the user to Choose filters or skip. Make clear that active filtering starts only after rubrics and the approved message template are saved; do not say filtering the batch before rubrics and message approval are saved. If the user skips filters, go directly to message template review once the review batch is ready."
1096
1141
  },
1097
1142
  {
1098
1143
  "tool": "update_campaign",
@@ -1139,7 +1184,7 @@
1139
1184
  ],
1140
1185
  "transitions": {
1141
1186
  "filters_enabled": "post-lead-workstreams",
1142
- "filters_skipped": "messages-mode-choice",
1187
+ "filters_skipped": "message-generation",
1143
1188
  "revise_leads": "find-leads"
1144
1189
  },
1145
1190
  "interruptOnly": true,
@@ -1185,7 +1230,6 @@
1185
1230
  {
1186
1231
  "name": "message-generation",
1187
1232
  "target": "generate-messages",
1188
- "mode": "DRY MODE",
1189
1233
  "inputs": [
1190
1234
  "campaignBrief",
1191
1235
  "selected source decision",
@@ -1202,15 +1246,17 @@
1202
1246
  "message-prep.md",
1203
1247
  "message-candidate-drafts.md"
1204
1248
  ],
1205
- "ownership": "proof inventory, token strategy, angle drafting, skeptical-prospect review, and selected winner only"
1249
+ "ownership": "proof inventory, token strategy, angle drafting, skeptical-prospect review, and selected winner only",
1250
+ "mode": "background_template_builder_reuse_or_launch_if_missing",
1251
+ "alreadyStartedBy": "auto-execute-leads.launch_message_draft_builder_after_review_batch_import"
1206
1252
  }
1207
1253
  ],
1208
- "earlyMessageStartRule": "After auto-execute-leads confirms the 15-row review batch, workflowTableId is ready, and the user has reached filter choice, the Message Draft Builder may start from campaignBrief, selected source state, selectedLeadListId, and imported campaign table rows, including while the user is on filter choice. This background template draft is provisional speed work only. The message worker must load the full generate-messages prompt; parent-thread fallback loads the same prompt and may use references/message-review-safety-gate.md only as a supplemental approval checklist. Legacy/resume preview prep still requires at least 3 probable good-fit rows. It may run beside filter-leads, but product Generate Message cells cannot queue until save_rubrics and update_campaign_brief both succeed.",
1254
+ "earlyMessageStartRule": "After auto-execute-leads confirms the 15-row review batch, workflowTableId is ready, and get_rows_minimal proves rows exist, the Message Draft Builder must start immediately from campaignBrief, selected source state, selectedLeadListId, and imported campaign table rows. post-lead-workstreams must reuse that in-flight message branch; if it is missing, launch it before saving rubrics or claiming message progress. This background template draft is provisional speed work only. The message worker must load the full generate-messages prompt; parent-thread fallback loads the same prompt and may use references/message-review-safety-gate.md only as a supplemental approval checklist. It may run beside filter-leads, but no enrichment, ICP scoring, filtering, or product Generate Message cells can queue until save_rubrics and update_campaign_brief both succeed.",
1209
1255
  "finalMessageReconcileRule": "The message recommendation may start before lead-filter.md exists, but before message-review it must cite only imported review-batch rows that still pass the saved rubric/filter results. If the selected winner depends on a row later excluded by saved filters, revise message-generation before message review.",
1210
- "finalTemplateReviewLockRule": "cannot start template review until filter choice is answered and the user chooses Use Template in Messages. If filters are enabled, lock template review until saved rubrics exist, a bounded filter run has completed, and there are usable passing/probably passing rows. prefer at least 2 usable passing rows for template review; if only 1 passes, show weak-sample copy and ask whether to continue, revise, import more, or skip filters. If filters are skipped, route to Messages mode choice once the review batch is ready. AI Generated is an explicit opt-out and must cancel or ignore the background template draft.",
1211
- "claudeRule": "In Claude Code, launch both returned post-find-leads scouts with Task/Agent subagents in the same assistant message only when the current session lists those agent names. Do not run filter first and then message generation unless subagents/background work are unavailable.",
1212
- "codexRule": "In Codex, launch both returned post-find-leads scout names as disjoint subagents in the same assistant turn only when the host exposes those custom agents for this run. If the host cannot spawn them, run the same branches sequentially and say so.",
1213
- "fallback": "If real parallel branches are unavailable or the named agents are absent, run filter-leads and then message-generation in the parent thread with product MCP tools/assets. Do not customer-surface agent install status, and do not claim background or parallel work in that fallback."
1256
+ "finalTemplateReviewLockRule": "template review does not require a Use Template vs AI Generated mode choice. After filters are enabled, lock template review until saved rubrics exist and the draft reconciles to the approved brief, selected source, and imported review batch. Keep the watched browser on Filter Leads while approval is pending. After approval writes the Approved Message Template into campaignBrief, queue enrichment/ICP scoring for the bounded review batch; prefer at least 2 usable passing/probably passing rows before moving the watched browser to Messages, with weak-sample escalation if only 1 passes.",
1257
+ "claudeRule": "In Claude Code, launch the returned message-generation scout immediately after post-import rows exist, then launch/reuse the filter-leads scout when the user chooses filters. When both named agents are available and both branches are ready in the same assistant message, use Task/Agent subagents in parallel; otherwise never claim background message progress until message-generation actually started.",
1258
+ "codexRule": "In Codex, launch the returned message-generation scout immediately after post-import rows exist, then launch/reuse filter-leads when filters are chosen. Use disjoint subagents only when the host exposes those custom agents; otherwise start the same message-generation branch in the parent thread before reporting it as running.",
1259
+ "fallback": "If real parallel branches are unavailable or the named agents are absent, start message-generation in the parent thread immediately after post-import, then run filter-leads from the same imported review batch. Do not customer-surface agent install status, and do not claim background or parallel work unless that work actually started."
1214
1260
  },
1215
1261
  {
1216
1262
  "action": "wait_for_lead_filter_rules",
@@ -1223,7 +1269,7 @@
1223
1269
  "message-prep.md",
1224
1270
  "message-candidate-drafts.md"
1225
1271
  ],
1226
- "rule": "Do not wait for message-validation.md before saving rubrics and moving the watched browser to Filter Leads. lead-filter.md is a debug artifact name; the durable requirement is production-safe rubric rules derived from the live campaign table review batch. Message work may still be running while the user watches fit filtering."
1272
+ "rule": "Do not wait for message-validation.md before saving rubrics and moving the watched browser to Filter Leads. lead-filter.md is a debug artifact name; the durable requirement is production-safe rubric rules derived from the live campaign table review batch. Message work may still be drafting while the user watches Filter Leads, but enrichment/filtering stays unqueued until the approved message template is saved to the campaign brief."
1227
1273
  },
1228
1274
  {
1229
1275
  "action": "save_filter_rubrics_to_campaign",
@@ -1257,50 +1303,10 @@
1257
1303
  "enableICPFilters": true,
1258
1304
  "watchNarration.stage": "fit-message"
1259
1305
  },
1260
- "watchNarrationRule": "Headline should be like `Filtering the review batch`. Body should say the browser is on Filter Leads, Codex saved the fit rules, and the review rows are being checked while the first message sample finishes. Next should point to message review.",
1261
- "when": "after_save_rubrics_succeeds_before_waiting_for_message_validation",
1306
+ "watchNarrationRule": "Headline should be like `Drafting the message template`. Body should say the browser is staying on Filter Leads with fit rules saved, Codex is finishing the reusable first-message template, and no enrichment/filtering or Generate Message cells run until that template is approved and saved to the campaign brief. Next should point to message template approval in chat.",
1307
+ "when": "after_save_rubrics_succeeds_before_waiting_for_message_validation_or_queueing_enrichment",
1262
1308
  "writesCampaignState": "currentStep:apply-icp-rubric"
1263
1309
  },
1264
- {
1265
- "tool": "get_rows_minimal",
1266
- "requiredValues": {
1267
- "tableId": "workflowTableId",
1268
- "limit": "import.importLimit"
1269
- },
1270
- "purpose": "read_bounded_review_batch_cell_ids_before_filter_wait",
1271
- "requiredBeforeCascade": true
1272
- },
1273
- {
1274
- "tool": "queue_cells",
1275
- "requiredValues": {
1276
- "tableId": "workflowTableId",
1277
- "cellSource": "bounded_review_batch_enrichCellIds",
1278
- "statusFilter": [
1279
- "pending",
1280
- "error",
1281
- "dependency_blocked"
1282
- ]
1283
- },
1284
- "purpose": "queue_bounded_review_batch_enrichment_before_waiting_for_rubric_results",
1285
- "rule": "Queue only enrichCellId values from get_rows_minimal for the bounded review batch. Do not queue icpCellId values or whole-table cells; the workflow cascade runs ICP scoring after enrichment."
1286
- },
1287
- {
1288
- "tool": "wait_for_rubric_results",
1289
- "requiredValues": {
1290
- "includeRows": false,
1291
- "minPassedCount": 1,
1292
- "targetCount": "bounded review batch count"
1293
- },
1294
- "purpose": "wait_for_bounded_filter_run_before_messages_mode",
1295
- "readVia": "stats_only_tool_result",
1296
- "note": "After filtered sample passes, Messages first shows mode choice. Prefer at least 2 usable passing/probably passing rows before Use Template review; if only 1 passes, show weak-sample copy and ask whether to continue, revise, import more, or skip filters."
1297
- },
1298
- {
1299
- "action": "require_usable_filtered_rows_before_messages_mode",
1300
- "after": "wait_for_rubric_results",
1301
- "requiredBeforeMessagesMode": true,
1302
- "rule": "If filters are enabled, do not show template review until saved rubrics and a bounded filter run have usable passing/probably passing rows. After the filtered sample passes, route to Messages mode choice before any template review."
1303
- },
1304
1310
  {
1305
1311
  "tool": "get_campaign_navigation_state",
1306
1312
  "purpose": "confirm the watched UI moved to Filter Leads after rubrics saved",
@@ -1336,9 +1342,6 @@
1336
1342
  "get_subskill_asset",
1337
1343
  "get_post_find_leads_scout_registry",
1338
1344
  "save_rubrics",
1339
- "get_rows_minimal",
1340
- "queue_cells",
1341
- "wait_for_rubric_results",
1342
1345
  "update_campaign",
1343
1346
  "get_campaign_navigation_state",
1344
1347
  "Task",
@@ -1348,10 +1351,10 @@
1348
1351
  ],
1349
1352
  "toolRules": [
1350
1353
  "The post-lead workstreams are disjoint: filter-leads owns lead-filter.md/rubric.json; message-generation owns message-validation.md/message-prep.md/message-candidate-drafts.md.",
1351
- "message-generation can start before saved filters, but message-review cannot start until saved filters and the message recommendation reconcile against the same imported review-batch rows.",
1354
+ "message-generation must start immediately after the post-import review batch exists, before saved filters; message-review cannot start until saved filters and the message recommendation reconcile against the same imported review-batch rows.",
1352
1355
  "Do not let filter-leads create a new message sample. Do not let message-generation fetch new prospects.",
1353
1356
  "Before writing message-validation.md or returning a template recommendation, message-generation must load the full get_subskill_prompt({ subskillName: \"generate-messages\" }) prompt and use campaignBrief, selected source state, selectedLeadListId, and imported review-batch rows as the source of truth. Optional debug markdown files are not durable state.",
1354
- "Do not queue before saved rubrics. After save_rubrics succeeds, queue only bounded review-batch enrichCellId values from get_rows_minimal before wait_for_rubric_results.",
1357
+ "Do not queue enrichment, ICP scoring, filtering, or Generate Message cells after saved rubrics alone. Wait until the approved message template is synced into campaignBrief, then queue only bounded review-batch enrichCellId values.",
1355
1358
  "Do not attach sequence, start, or queue product Generate Message cells until the approved message set is synced into campaignBrief."
1356
1359
  ],
1357
1360
  "doNotAllow": [
@@ -1369,15 +1372,14 @@
1369
1372
  "post_lead_workstreams_ready",
1370
1373
  "revise_leads",
1371
1374
  "revise_rubric",
1372
- "revise_messaging",
1373
- "confirm_with_user"
1375
+ "revise_messaging"
1374
1376
  ],
1375
1377
  "transitions": {
1376
- "post_lead_workstreams_ready": "messages-mode-choice",
1378
+ "post_lead_workstreams_ready": "message-review",
1377
1379
  "revise_leads": "find-leads",
1378
1380
  "revise_rubric": "filter-rubric",
1379
1381
  "revise_messaging": "message-generation",
1380
- "confirm_with_user": "messages-mode-choice"
1382
+ "confirm_with_user": "message-review"
1381
1383
  },
1382
1384
  "interruptOnly": true,
1383
1385
  "requiredCampaignState": [
@@ -1397,46 +1399,12 @@
1397
1399
  {
1398
1400
  "id": "messages-mode-choice",
1399
1401
  "label": "Messages mode choice",
1400
- "currentStepValue": "messages",
1401
- "normalFlow": true,
1402
+ "currentStepValue": null,
1403
+ "normalFlow": false,
1402
1404
  "onEnter": [
1403
1405
  {
1404
- "tool": "update_campaign",
1405
- "requiredValues": {
1406
- "currentStep": "messages",
1407
- "watchNarration.stage": "fit-message"
1408
- },
1409
- "watchNarrationRule": "Messages first shows a mode choice, not final review: Use Template and AI Generated. Use Template is recommended because it uses the approved campaign brief and review-batch evidence. AI Generated is an explicit opt-out from the background template draft. Do not show Review fit and message until the user chooses a mode and a reviewable message/template exists."
1410
- },
1411
- {
1412
- "action": "show_messages_mode_choice",
1413
- "choices": [
1414
- "Use Template (recommended)",
1415
- "AI Generated"
1416
- ],
1417
- "copyRule": "Show Use Template first and mark it recommended. Explain that Use Template reviews the Message Draft Builder template before any Generate Message cells run. Explain that AI Generated is an explicit opt-out."
1418
- },
1419
- {
1420
- "action": "wait_for_message_draft_builder_when_use_template",
1421
- "when": "user chose Use Template and draft is not ready",
1422
- "copy": "I am waiting for the Message Draft Builder. I will show the template when it is ready; I am not asking for approval yet.",
1423
- "forbiddenApprovalCopy": true
1424
- },
1425
- {
1426
- "action": "handle_unusable_or_unknown_template_draft",
1427
- "when": "draft worker fails, produces no usable message, or worker status is unknown",
1428
- "requiredCopy": "retry or regenerate the template draft before approval",
1429
- "forbiddenApprovalCopy": true
1430
- },
1431
- {
1432
- "action": "cancel_or_ignore_background_template_on_ai_generated",
1433
- "when": "user chose AI Generated",
1434
- "rule": "AI Generated is an explicit opt-out: cancel or ignore the background template draft and must not let late background template draft output overwrite campaign state."
1435
- },
1436
- {
1437
- "action": "route_ai_generated_to_product_path",
1438
- "when": "user chose AI Generated",
1439
- "rule": "Continue through the explicit AI-generated product path. Route to auto-execute-messaging when product row generation is required first; do not transition to validate-sample as the normal path."
1406
+ "action": "legacy_resume_only_notice",
1407
+ "rule": "Do not show this question in normal create-campaign runs. Route to message-generation/message-review instead."
1440
1408
  }
1441
1409
  ],
1442
1410
  "allowedTools": [
@@ -1457,16 +1425,10 @@
1457
1425
  ],
1458
1426
  "watchRequired": true,
1459
1427
  "waitFor": [
1460
- "use_template_ready",
1461
- "use_template_waiting",
1462
- "ai_generated_selected",
1463
- "revise_messaging"
1428
+ "legacy_resume_only"
1464
1429
  ],
1465
1430
  "transitions": {
1466
- "use_template_ready": "message-review",
1467
- "use_template_waiting": "message-generation",
1468
- "ai_generated_selected": "auto-execute-messaging",
1469
- "revise_messaging": "message-generation"
1431
+ "legacy_resume_only": "message-generation"
1470
1432
  },
1471
1433
  "interruptOnly": true,
1472
1434
  "requiredCampaignState": [
@@ -1474,7 +1436,10 @@
1474
1436
  "campaignBrief",
1475
1437
  "selectedLeadListId",
1476
1438
  "workflowTableId"
1477
- ]
1439
+ ],
1440
+ "resumeOnly": true,
1441
+ "deprecated": true,
1442
+ "deprecatedReason": "Default create-campaign flow no longer asks Use Template vs AI Generated. Message Draft Builder template review is the only normal path; AI-generated mode is legacy/manual only."
1478
1443
  },
1479
1444
  {
1480
1445
  "id": "filter-rubric",
@@ -1631,7 +1596,7 @@
1631
1596
  "Do not hand-write message-validation.md from message-prep.md, message-candidate-drafts.md, stale markdown files, database reads, or general campaign knowledge.",
1632
1597
  "message-validation.md or the returned recommendation must prove the generate-messages workflow ran and include Token Fill Rules, good-fill and omit/fallback examples, a raw sendable selected winner, and quality gate notes before message-review can recommend approve-message.",
1633
1598
  "If the generate-messages output is plausible but weaker than the gold-standard rules, stop at message-review with revise-messaging. Do not continue to approval or mint just because the mechanical flow worked.",
1634
- "The approved message set must be written back into campaignBrief before auto-execute-messaging observes or queues product Generate Message cells. AI Generated mode uses the product's AI-generated path instead of template review."
1599
+ "The approved message set must be written back into campaignBrief before auto-execute-messaging observes or queues product Generate Message cells. Normal create-campaign runs use the approved-template path; legacy AI-generated mode is not part of the normal flow."
1635
1600
  ],
1636
1601
  "doNotAllow": [
1637
1602
  "create_campaign",
@@ -1823,19 +1788,51 @@
1823
1788
  "writesCampaignState": "campaignBrief.Approved Message Template"
1824
1789
  },
1825
1790
  {
1826
- "action": "advance_watch_to_messaging_after_message_approval",
1791
+ "tool": "get_rows_minimal",
1792
+ "purpose": "read_bounded_review_batch_cell_ids_after_message_approval",
1793
+ "requiredBeforeCascade": true
1794
+ },
1795
+ {
1796
+ "tool": "queue_cells",
1797
+ "requiredValues": {
1798
+ "tableId": "workflowTableId",
1799
+ "cellSource": "bounded_review_batch_enrichCellIds",
1800
+ "statusFilter": [
1801
+ "pending",
1802
+ "error",
1803
+ "dependency_blocked"
1804
+ ]
1805
+ },
1806
+ "purpose": "queue_bounded_review_batch_enrichment_after_approved_template",
1807
+ "rule": "Queue only enrichCellId values from get_rows_minimal for the bounded review batch after update_campaign_brief has saved the Approved Message Template. Do not queue Generate Message cells directly here; the workflow cascade runs enrichment, ICP scoring, then Generate Message for passing rows."
1808
+ },
1809
+ {
1810
+ "tool": "wait_for_rubric_results",
1811
+ "requiredValues": {
1812
+ "includeRows": false,
1813
+ "minPassedCount": 2,
1814
+ "targetCount": "bounded review batch count"
1815
+ },
1816
+ "purpose": "wait_for_bounded_filter_run_after_message_approval_before_messages_step",
1817
+ "readVia": "stats_only_tool_result",
1818
+ "note": "After the approved template is saved, wait for the bounded enrichment/ICP scoring run to produce at least 2 usable passing/probably passing rows before moving the watched browser to Messages. If only 1 passes, use weak-sample escalation before continuing."
1819
+ },
1820
+ {
1821
+ "action": "advance_watch_to_messaging_after_filter_passes",
1827
1822
  "tool": "update_campaign",
1828
1823
  "requires": [
1829
1824
  "campaignId",
1830
- "message-review-decision.md"
1825
+ "message-review-decision.md",
1826
+ "campaignBrief.Approved Message Template",
1827
+ "bounded filter run with usable passing rows"
1831
1828
  ],
1832
1829
  "requiredValues": {
1833
1830
  "currentStep": "auto-execute-messaging",
1834
1831
  "enableICPFilters": true,
1835
1832
  "watchNarration.stage": "review-ready"
1836
1833
  },
1837
- "when": "after_update_campaign_brief_succeeds",
1838
- "requiredBeforeCascade": true,
1834
+ "when": "after_update_campaign_brief_succeeds_and_bounded_filter_run_has_passing_rows",
1835
+ "requiredBeforeGenerateMessageCascade": true,
1839
1836
  "writesCampaignState": "currentStep:auto-execute-messaging"
1840
1837
  }
1841
1838
  ],
@@ -1857,14 +1854,16 @@
1857
1854
  "request_user_input",
1858
1855
  "get_subskill_prompt",
1859
1856
  "update_campaign_brief",
1860
- "update_campaign"
1857
+ "update_campaign",
1858
+ "get_rows_minimal",
1859
+ "queue_cells",
1860
+ "wait_for_rubric_results"
1861
1861
  ],
1862
1862
  "doNotAllow": [
1863
1863
  "create_campaign",
1864
1864
  "save_rubrics",
1865
1865
  "import_leads",
1866
1866
  "confirm_lead_list",
1867
- "queue_cells",
1868
1867
  "start_campaign",
1869
1868
  "enrich_with_prospeo",
1870
1869
  "bulk_enrich_with_prospeo"
@@ -2253,7 +2252,7 @@
2253
2252
  "currentStepValue": "validate-sample",
2254
2253
  "normalFlow": false,
2255
2254
  "resumeOnly": true,
2256
- "deprecatedReason": "Recovery/legacy only. The normal Phase 135 path reaches Messages after the filtered sample passes, then routes Use Template approval or AI Generated choice to auto-execute-messaging.",
2255
+ "deprecatedReason": "Recovery/legacy only. The normal path reaches Messages only after the approved template is saved, enrichment/ICP scoring runs, and the filtered sample has usable passing rows.",
2257
2256
  "reference": "references/sample-validation-loop.md",
2258
2257
  "counter": {
2259
2258
  "name": "revisionRound",
@@ -2447,7 +2446,6 @@
2447
2446
  "action": "verify_campaign_brief_template_mode",
2448
2447
  "requiredSection": "Approved Message Template",
2449
2448
  "requiredPattern": "{{...}}",
2450
- "skipWhen": "messageMode is ai-generated",
2451
2449
  "onFailure": "runtime_failure_before_messaging",
2452
2450
  "repairBoundary": "before_import_only",
2453
2451
  "purpose": "ensure Generate Message uses the approved template instead of full-generation mode"
@@ -2458,7 +2456,7 @@
2458
2456
  },
2459
2457
  {
2460
2458
  "tool": "queue_cells",
2461
- "cellSource": "pending_generate_message_cells_for_passing_rows; in ai-generated mode use the explicit AI-generated product path, not the background template draft",
2459
+ "cellSource": "pending_generate_message_cells_for_passing_rows_using_approved_campaign_brief_template",
2462
2460
  "when": "any passing row has pending or empty Generate Message cell",
2463
2461
  "batchSize": 100
2464
2462
  },
@@ -2509,7 +2507,6 @@
2509
2507
  "proposed_token_never_persisted_in_rewrite",
2510
2508
  "generate_messages_must_re_cascade_on_newly_passed_rows",
2511
2509
  "campaign_brief_must_contain_approved_message_template_tokens_before_generate_message_cascade",
2512
- "ai_generated_mode_uses_explicit_product_path_and_ignores_background_template_draft",
2513
2510
  "generate_message_cells_do_not_run_from_background_template_until_template_token_rules_approved"
2514
2511
  ],
2515
2512
  "watchRequired": true,
@@ -31,6 +31,13 @@ live on the campaign. Reuse that state. If anything is missing, do not replay
31
31
  the source inside Step 13; route back to find-leads so the source can be
32
32
  attached with `campaignOfferId` and the campaign UI can stay in sync.
33
33
 
34
+ Do not navigate the watched UI to the import/confirm page before the provider
35
+ import has started. Keep `currentStep` on the approved source lane while
36
+ `import_leads` calls the provider import API. `import_leads` then updates
37
+ `selectedLeadListId` and moves `currentStep` to `confirm-lead-list` only after
38
+ it has a lead-list table/job id, so the user lands on the import page with
39
+ progress state available instead of an empty waiting page.
40
+
34
41
  selectedLeadListId remains the source list; workflowTableId is the campaign
35
42
  table. The first confirm/import must preserve both identities.
36
43
 
@@ -201,6 +208,9 @@ cannot scale further without a new source lane.
201
208
 
202
209
  - `import_leads` with `mode=add` is ALWAYS a two-step handshake. Never
203
210
  treat the first `needsModeSelection=true` response as a failure.
211
+ - Step 13 entry does NOT set `currentStep` to `confirm-lead-list`. The watched
212
+ UI stays on the approved source lane until `import_leads` returns a lead-list
213
+ table/job id and moves the campaign to `confirm-lead-list`.
204
214
  - Dedup ratios (imported / skipped / duplicates) are always surfaced for
205
215
  escalation-logic input.
206
216
  - Zero-imported + zero-skipped ⇒ hard-fail escalate.
@@ -35,7 +35,7 @@ stage labels. The driver label comes from the watch URL mode (`mode=claude` or
35
35
  Apollo, or existing list.
36
36
  - During search iteration, say what you tried, what you are trying next, what
37
37
  sample you are checking, and why that helps this campaign.
38
- - At filter choice, do not say filtering the batch before rubrics are saved.
38
+ - At filter choice, do not say filtering the batch before rubrics and message approval are saved.
39
39
  - Avoid internal terms: MCP, tool, currentStep, workflow table, scout, debug.
40
40
  - Do not invent time estimates.
41
41
 
@@ -206,8 +206,8 @@ After review batch import:
206
206
 
207
207
  Use this after the selected review rows are present and before filters are
208
208
  saved. This is add-filters intent, not active filtering. Tell the user to
209
- Choose filters or skip, and do not say filtering the batch before rubrics are
210
- saved. When the user chooses filters, immediately persist
209
+ Choose filters or skip, and do not say filtering the batch before rubrics and
210
+ message approval are saved. When the user chooses filters, immediately persist
211
211
  `enableICPFilters: true` and move to `create-icp-rubric` so the watched app
212
212
  shows Filter Rules while Codex defines the rules in chat.
213
213
 
@@ -232,10 +232,10 @@ Review ready:
232
232
  ```json
233
233
  {
234
234
  "stage": "review-ready",
235
- "headline": "Choose message mode",
236
- "visibleState": "The Messages step shows Use Template and AI Generated.",
237
- "agentIntent": "Use Template is recommended. AI Generated is an explicit opt-out that cancels or ignores the background template draft.",
238
- "nextAction": "Validation",
235
+ "headline": "Review the message template",
236
+ "visibleState": "The browser remains on Filter Leads while the message template is reviewed in chat.",
237
+ "agentIntent": "Codex is waiting for approval before saving the template to the campaign brief and queueing enrichment/filtering.",
238
+ "nextAction": "Approve or revise the template",
239
239
  "safety": "Codex will only continue after you approve."
240
240
  }
241
241
  ```
@@ -246,10 +246,10 @@ Messages waiting for template:
246
246
  {
247
247
  "stage": "review-ready",
248
248
  "headline": "Waiting for the template",
249
- "visibleState": "Use Template is selected, but the Message Draft Builder is still finishing.",
249
+ "visibleState": "The fit rules are saved and the Message Draft Builder is still finishing.",
250
250
  "agentIntent": "Codex is waiting for the Message Draft Builder and will not ask for approval until the template can be reviewed.",
251
251
  "nextAction": "Review template",
252
- "safety": "Late template output must not overwrite campaign state if AI Generated was selected."
252
+ "safety": "No enrichment, filtering, or Generate Message cells run until the template is approved."
253
253
  }
254
254
  ```
255
255