@sellable/mcp 0.1.135 → 0.1.137
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/agents/post-find-leads-filter-scout.md +19 -25
- package/agents/post-find-leads-message-scout.md +52 -1
- package/agents/registry.json +15 -24
- package/agents/source-scout-linkedin-engagement.md +6 -3
- package/agents/source-scout-prospeo-contact.md +4 -2
- package/agents/source-scout-sales-nav.md +4 -2
- package/dist/tools/bootstrap.js +1 -1
- package/dist/tools/campaigns.js +0 -11
- package/dist/tools/leads.d.ts +14 -0
- package/dist/tools/leads.js +160 -15
- package/dist/tools/navigation.js +3 -0
- package/dist/tools/processing.js +1 -1
- package/dist/tools/prompts.d.ts +11 -4
- package/dist/tools/prompts.js +48 -4
- package/dist/tools/sequencer.d.ts +1 -0
- package/dist/tools/sequencer.js +1 -1
- package/package.json +1 -1
- package/skills/create-campaign-v2/SKILL.md +150 -1313
- package/skills/create-campaign-v2/core/flow.v2.json +369 -2183
- package/skills/create-campaign-v2/references/watch-guide-narration.md +12 -10
- package/skills/find-leads/SKILL.md +5 -2
- package/skills/generate-messages/SKILL.md +25 -0
- package/skills/providers/prospeo.md +5 -4
- package/skills/providers/sales-nav.md +1 -2
- package/skills/providers/signal-discovery.md +1 -1
|
@@ -1,15 +1,40 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "v2",
|
|
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.
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
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.",
|
|
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
|
+
"legacyCompatibility": {
|
|
7
|
+
"validationSubskill": "create-campaign-v2-validation",
|
|
8
|
+
"tailSubskill": "create-campaign-v2-tail",
|
|
9
|
+
"rule": "Legacy validation/rehearsal files are opt-in diagnostics only and are not active flow gates."
|
|
10
10
|
},
|
|
11
|
+
"commitGateChoices": [
|
|
12
|
+
"approve",
|
|
13
|
+
"revise-brief",
|
|
14
|
+
"revise-leads",
|
|
15
|
+
"revise-rubric",
|
|
16
|
+
"revise-messaging",
|
|
17
|
+
"abort"
|
|
18
|
+
],
|
|
19
|
+
"canonicalStateFields": [
|
|
20
|
+
"campaignId",
|
|
21
|
+
"watchUrl",
|
|
22
|
+
"campaignBrief",
|
|
23
|
+
"currentStep",
|
|
24
|
+
"watchNarration",
|
|
25
|
+
"providerSearchAssociation",
|
|
26
|
+
"selectedLeadListId",
|
|
27
|
+
"workflowTableId",
|
|
28
|
+
"filterChoice",
|
|
29
|
+
"leadScoringRubrics",
|
|
30
|
+
"messageDraftRecommendation",
|
|
31
|
+
"approvedMessageTemplate",
|
|
32
|
+
"senderIds",
|
|
33
|
+
"sequenceTemplate",
|
|
34
|
+
"runningState"
|
|
35
|
+
],
|
|
11
36
|
"watchNarrationTransitionContract": {
|
|
12
|
-
"rule": "Every watched currentStep switch must
|
|
37
|
+
"rule": "Every watched currentStep switch must include fresh watchNarration.",
|
|
13
38
|
"requiredFields": [
|
|
14
39
|
"stage",
|
|
15
40
|
"headline",
|
|
@@ -20,72 +45,42 @@
|
|
|
20
45
|
"copyMustInclude": [
|
|
21
46
|
"what just happened",
|
|
22
47
|
"current visible page/state",
|
|
23
|
-
"next user action"
|
|
24
|
-
"safety boundary when work is gated"
|
|
48
|
+
"next user action"
|
|
25
49
|
],
|
|
26
50
|
"appliesToTools": [
|
|
27
51
|
"create_campaign",
|
|
28
52
|
"update_campaign",
|
|
29
|
-
"update_campaign_brief when it unlocks a step",
|
|
30
|
-
"attach_selected_sender",
|
|
31
53
|
"attach_recommended_sequence",
|
|
32
54
|
"start_campaign"
|
|
33
55
|
]
|
|
34
56
|
},
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"user_revise_brief",
|
|
63
|
-
"user_revise_leads",
|
|
64
|
-
"user_revise_rubric",
|
|
65
|
-
"user_revise_messaging",
|
|
66
|
-
"user_abort",
|
|
67
|
-
"rubrics_saved",
|
|
68
|
-
"watch_link_surfaced",
|
|
69
|
-
"autonomous_tail_started",
|
|
70
|
-
"leads_imported",
|
|
71
|
-
"sample_validated",
|
|
72
|
-
"sample_revision_required",
|
|
73
|
-
"review_batch_ready",
|
|
74
|
-
"awaiting_user_greenlight",
|
|
75
|
-
"user_greenlight",
|
|
76
|
-
"campaign_started",
|
|
77
|
-
"escalation_triggered",
|
|
78
|
-
"campaign_shell_created",
|
|
79
|
-
"campaign_shell_brief_synced",
|
|
80
|
-
"source_synced_to_campaign",
|
|
81
|
-
"rubric_saved_to_campaign",
|
|
82
|
-
"message_set_synced_to_brief",
|
|
83
|
-
"review_batch_imported",
|
|
84
|
-
"settings_link_surfaced",
|
|
85
|
-
"sender_connection_required",
|
|
86
|
-
"sender_attached",
|
|
87
|
-
"ready_to_launch",
|
|
88
|
-
"sequence_attached"
|
|
57
|
+
"lazyReferences": {
|
|
58
|
+
"watch": [
|
|
59
|
+
"references/watch-link-handoff.md",
|
|
60
|
+
"references/watch-guide-narration.md"
|
|
61
|
+
],
|
|
62
|
+
"source": [
|
|
63
|
+
"references/lead-validation-preview.md",
|
|
64
|
+
"references/step-13-import-leads.md"
|
|
65
|
+
],
|
|
66
|
+
"filter": [
|
|
67
|
+
"references/filter-leads.md"
|
|
68
|
+
],
|
|
69
|
+
"message": [
|
|
70
|
+
"references/message-review-safety-gate.md"
|
|
71
|
+
],
|
|
72
|
+
"tail": [
|
|
73
|
+
"references/sample-validation-loop.md",
|
|
74
|
+
"references/step-15-re-cascade.md",
|
|
75
|
+
"references/final-handoff-contract.md"
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
"safetyBoundaries": [
|
|
79
|
+
"Do not call list_senders before Settings after message approval.",
|
|
80
|
+
"Do not import leads until the source decision is approved.",
|
|
81
|
+
"Do not queue cells until the bounded review batch exists and the message/filter gates are satisfied.",
|
|
82
|
+
"Do not call start_campaign until the user explicitly confirms launch.",
|
|
83
|
+
"Do not use local files as durable state in normal customer runs."
|
|
89
84
|
],
|
|
90
85
|
"steps": [
|
|
91
86
|
{
|
|
@@ -102,39 +97,28 @@
|
|
|
102
97
|
"tool": "get_subskill_prompt",
|
|
103
98
|
"requiredValues": {
|
|
104
99
|
"subskillName": "create-campaign-v2"
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
{
|
|
108
|
-
"tool": "get_subskill_asset",
|
|
109
|
-
"requiredValues": {
|
|
110
|
-
"subskillName": "create-campaign-v2",
|
|
111
|
-
"assetPath": "core/flow.v2.json"
|
|
112
|
-
}
|
|
100
|
+
},
|
|
101
|
+
"purpose": "load the compact entry prompt once"
|
|
113
102
|
}
|
|
114
103
|
],
|
|
115
|
-
"requiredArtifacts": [],
|
|
116
|
-
"producesArtifacts": [],
|
|
117
104
|
"allowedTools": [
|
|
118
105
|
"bootstrap_create_campaign",
|
|
119
106
|
"get_auth_status",
|
|
120
107
|
"get_active_workspace",
|
|
121
108
|
"get_subskill_prompt",
|
|
122
|
-
"get_subskill_asset",
|
|
123
109
|
"AskUserQuestion",
|
|
124
110
|
"request_user_input"
|
|
125
111
|
],
|
|
126
112
|
"doNotAllow": [
|
|
127
113
|
"create_campaign",
|
|
114
|
+
"list_senders",
|
|
128
115
|
"save_rubrics",
|
|
129
116
|
"import_leads",
|
|
130
117
|
"confirm_lead_list",
|
|
131
118
|
"update_campaign",
|
|
132
119
|
"queue_cells",
|
|
133
|
-
"start_campaign"
|
|
134
|
-
"enrich_with_prospeo",
|
|
135
|
-
"bulk_enrich_with_prospeo"
|
|
120
|
+
"start_campaign"
|
|
136
121
|
],
|
|
137
|
-
"watchRequired": false,
|
|
138
122
|
"waitFor": "bootstrap_complete",
|
|
139
123
|
"transitions": {
|
|
140
124
|
"bootstrap_complete": "brief-interview"
|
|
@@ -142,46 +126,24 @@
|
|
|
142
126
|
},
|
|
143
127
|
{
|
|
144
128
|
"id": "brief-interview",
|
|
145
|
-
"label": "
|
|
129
|
+
"label": "Identity, research, and brief",
|
|
146
130
|
"onEnter": [
|
|
147
131
|
{
|
|
148
132
|
"action": "resolve_campaign_identity_before_strategy_packet",
|
|
149
|
-
"optional": false,
|
|
150
|
-
"when": "before_founder_strategy_source_packet",
|
|
151
133
|
"allowedTools": [
|
|
152
134
|
"fetch_company",
|
|
153
135
|
"fetch_linkedin_profile",
|
|
154
136
|
"WebFetch",
|
|
155
137
|
"WebSearch"
|
|
156
138
|
],
|
|
157
|
-
"maxCalls": {
|
|
158
|
-
"identityLookup": 1,
|
|
159
|
-
"companyLookupAfterIdentityConfirm": 1
|
|
160
|
-
},
|
|
161
|
-
"quietlyCheckConnectedSendersFirst": false,
|
|
162
|
-
"preferUserLinkedInWhenSenderInferenceIsWeak": true,
|
|
163
|
-
"doNotPresentSenderPickerBeforeIdentityInference": true,
|
|
164
|
-
"confirmCompanyBeforeStrategyQuestions": true,
|
|
165
139
|
"mustNotInferFromNameOnly": true,
|
|
166
|
-
"
|
|
167
|
-
|
|
168
|
-
{
|
|
169
|
-
"action": "confirm_ambiguous_campaign_focus_with_structured_gate",
|
|
170
|
-
"when": "after_identity_before_founder_strategy_source_packet",
|
|
171
|
-
"allowedTools": [
|
|
172
|
-
"AskUserQuestion",
|
|
173
|
-
"request_user_input"
|
|
174
|
-
],
|
|
175
|
-
"questionType": "single-choice only; plain chat only for free-text custom detail",
|
|
176
|
-
"multiSelect": false,
|
|
177
|
-
"maxOptions": 4,
|
|
178
|
-
"requiredOption": "Other / custom",
|
|
179
|
-
"chatRenderRule": "If the sender/company context has multiple campaignable product lines, services, or offers, ask exactly one single-choice structured campaign-focus question before buyer/offer/proof/source. Do not ask numbered plain-chat choices when the structured question tool is available. Do not use checkbox or multi-select wording."
|
|
140
|
+
"doNotPresentSenderPickerBeforeIdentityInference": true,
|
|
141
|
+
"fallback": "Ask for the LinkedIn profile or company website before strategy questions."
|
|
180
142
|
},
|
|
181
143
|
{
|
|
182
144
|
"action": "run_campaign_identity_research_before_strategy_packet",
|
|
183
145
|
"target": "research-sender",
|
|
184
|
-
"
|
|
146
|
+
"requiredCompletion": "complete_sender_research",
|
|
185
147
|
"allowedTools": [
|
|
186
148
|
"get_subskill_prompt",
|
|
187
149
|
"fetch_linkedin_profile",
|
|
@@ -190,112 +152,19 @@
|
|
|
190
152
|
"fetch_company_posts",
|
|
191
153
|
"WebFetch",
|
|
192
154
|
"WebSearch",
|
|
193
|
-
"ToolSearch",
|
|
194
155
|
"complete_sender_research"
|
|
195
|
-
],
|
|
196
|
-
"requiredCompletion": "complete_sender_research",
|
|
197
|
-
"fallback": "If WebSearch is unavailable, use available MCP profile/company/post tools, call complete_sender_research with observed counts, and carry explicit proof gaps into the setup packet.",
|
|
198
|
-
"chatRenderRule": "Use researched company positioning and proof options in the buyer/offer/proof/source setup packet; do not ask generic strategy questions from company name alone."
|
|
199
|
-
},
|
|
200
|
-
{
|
|
201
|
-
"action": "skip_strategy_packet_when_initial_context_is_sufficient",
|
|
202
|
-
"when": "after_identity_lookup_before_founder_strategy_source_packet",
|
|
203
|
-
"condition": "initial invocation or first operator answer includes identity/client context, target prospects, offer/CTA, proof guidance, and lead-source preference or permission to find people",
|
|
204
|
-
"requiredCoveredFields": [
|
|
205
|
-
"identity_or_client_context",
|
|
206
|
-
"target_prospects",
|
|
207
|
-
"offer_or_cta",
|
|
208
|
-
"proof_guidance",
|
|
209
|
-
"lead_source_preference_or_find_people_permission"
|
|
210
|
-
],
|
|
211
|
-
"effect": "mark founder_strategy_source_packet_answered and proceed to render_post_intake_progress_preamble without asking setup questions again",
|
|
212
|
-
"askOnlyWhen": [
|
|
213
|
-
"a required covered field is missing",
|
|
214
|
-
"the supplied inputs conflict",
|
|
215
|
-
"the campaign focus is genuinely ambiguous"
|
|
216
|
-
],
|
|
217
|
-
"chatRenderRule": "State the inferred campaign direction in one or two lines and draft the brief. Do not ask buyer, offer, proof, or source setup questions just to restate information the operator already supplied; the brief approval gate is the correction point."
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
"action": "ask_source_intake_after_strategy_batch",
|
|
221
|
-
"artifact": "lead-source-intake.json",
|
|
222
|
-
"optional": true,
|
|
223
|
-
"skipWhen": "skip_strategy_packet_when_initial_context_is_sufficient matched",
|
|
224
|
-
"question": "How should we get the people for this campaign?",
|
|
225
|
-
"options": [
|
|
226
|
-
"Find people for me (recommended if you don't already have your own list)",
|
|
227
|
-
"I have a CSV of profiles to reach out to",
|
|
228
|
-
"I have a CSV of companies/domains I want to target"
|
|
229
|
-
],
|
|
230
|
-
"forbiddenOptionLabels": [
|
|
231
|
-
"engagers",
|
|
232
|
-
"titles",
|
|
233
|
-
"Signals",
|
|
234
|
-
"Sales Nav",
|
|
235
|
-
"Prospeo",
|
|
236
|
-
"search LinkedIn posts"
|
|
237
|
-
],
|
|
238
|
-
"forbiddenOptionLabelReason": "Provider/source mechanics are internal to the 'Find people for me' path; first-time users should choose the job they need done, not the scouting provider.",
|
|
239
|
-
"customInput": true,
|
|
240
|
-
"multiSelect": false,
|
|
241
|
-
"lastQuestionInFirstStrategyBatch": true
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
"action": "render_post_intake_progress_preamble",
|
|
245
|
-
"after": "founder_strategy_source_packet_answered",
|
|
246
|
-
"requiredVisibleContent": [
|
|
247
|
-
"turn this into a campaign brief",
|
|
248
|
-
"create the campaign shell with the brief already in it",
|
|
249
|
-
"watch the draft campaign as it fills in",
|
|
250
|
-
"no leads import and nothing sends yet"
|
|
251
|
-
],
|
|
252
|
-
"forbiddenWording": [
|
|
253
|
-
"brief.md",
|
|
254
|
-
"lead-review.md",
|
|
255
|
-
"lead-sample.json",
|
|
256
|
-
"message-validation.md"
|
|
257
156
|
]
|
|
258
157
|
},
|
|
259
158
|
{
|
|
260
|
-
"action": "
|
|
261
|
-
"
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
"
|
|
265
|
-
"requiredVisibleContent": [
|
|
266
|
-
"Campaign brief",
|
|
267
|
-
"Decision",
|
|
268
|
-
"Target",
|
|
269
|
-
"Pain",
|
|
270
|
-
"Offer",
|
|
271
|
-
"Proof",
|
|
272
|
-
"Lead plan",
|
|
273
|
-
"Risks",
|
|
274
|
-
"What happens next"
|
|
275
|
-
],
|
|
276
|
-
"mustRunBefore": [
|
|
277
|
-
"optional_debug_artifact_writer",
|
|
278
|
-
"Bash",
|
|
279
|
-
"mkdir"
|
|
280
|
-
],
|
|
281
|
-
"chatRenderRule": "After synthesizing the brief, render the approval-ready brief in chat before any optional local folder creation, file write, or artifact copy. Normal customer runs should not create local draft files here. The user should see useful brief content and live campaign state, not local persistence chrome. Do not ask the user to approve a hidden artifact."
|
|
282
|
-
},
|
|
283
|
-
{
|
|
284
|
-
"action": "optional_debug_artifact_writer",
|
|
285
|
-
"artifact": "brief.md",
|
|
286
|
-
"mode": "debug_or_uat_only",
|
|
287
|
-
"shouldNotRunInNormalCustomerPath": true,
|
|
288
|
-
"shouldNotBlockMainThread": true,
|
|
289
|
-
"allowedToRunWhileUserReviewsInlineBrief": true,
|
|
290
|
-
"fallback": "If debug/UAT artifacts are requested and no background writer is available, write brief.md synchronously only after the approval-ready brief is already visible in chat. In normal customer runs, skip the write.",
|
|
291
|
-
"chatRenderRule": "Do not surface folder/file-write progress in chat unless the write fails or the user asks. The main thread should keep the brief review moving from campaign state."
|
|
159
|
+
"action": "ask_campaign_focus_only_when_ambiguous",
|
|
160
|
+
"uses": "request_user_input",
|
|
161
|
+
"singleChoice": true,
|
|
162
|
+
"requiredOption": "Other / custom",
|
|
163
|
+
"neverCollectOpenTextWithStructuredQuestion": true
|
|
292
164
|
},
|
|
293
165
|
{
|
|
294
166
|
"action": "create_watchable_campaign_shell_with_v1_brief",
|
|
295
167
|
"tool": "create_campaign",
|
|
296
|
-
"artifact": "campaign-shell.json",
|
|
297
|
-
"when": "after_v1_brief_is_visible_and_before_brief_review",
|
|
298
|
-
"mode": "shell-first-campaign",
|
|
299
168
|
"requiredFields": [
|
|
300
169
|
"name",
|
|
301
170
|
"campaignBrief",
|
|
@@ -305,222 +174,100 @@
|
|
|
305
174
|
],
|
|
306
175
|
"requiredValues": {
|
|
307
176
|
"currentStep": "create-offer",
|
|
308
|
-
"watchNarration.stage": "brief
|
|
177
|
+
"watchNarration.stage": "brief"
|
|
309
178
|
},
|
|
310
|
-
"briefMode": "v1 campaign brief shown to the user; not an empty placeholder",
|
|
311
179
|
"capture": [
|
|
312
180
|
"campaignId",
|
|
313
181
|
"watchUrl"
|
|
314
182
|
],
|
|
315
|
-
"surfaceWatchLink": true,
|
|
316
|
-
"watchLinkRule": "Show the link only after the brief is on the campaign, so the user lands on a useful brief instead of an empty campaign.",
|
|
317
|
-
"onFailure": "stop_and_surface_campaign_shell_creation_error; no no-shell mint fallback in shell-first flow",
|
|
318
|
-
"forbiddenUntilRubricAndMessageReady": [
|
|
319
|
-
"import_leads",
|
|
320
|
-
"confirm_lead_list",
|
|
321
|
-
"queue_cells",
|
|
322
|
-
"enrich_with_prospeo",
|
|
323
|
-
"bulk_enrich_with_prospeo"
|
|
324
|
-
],
|
|
325
|
-
"forbiddenUntilSenderAndSequenceReady": [
|
|
326
|
-
"start_campaign"
|
|
327
|
-
],
|
|
328
183
|
"canonicalStateWrites": [
|
|
329
184
|
"campaignId",
|
|
330
185
|
"watchUrl",
|
|
331
186
|
"campaignBrief",
|
|
332
|
-
"currentStep:create-offer"
|
|
333
|
-
"watchNarration: brief-review with approve-the-brief guidance"
|
|
187
|
+
"currentStep:create-offer"
|
|
334
188
|
]
|
|
335
189
|
},
|
|
336
190
|
{
|
|
337
191
|
"action": "surface_campaign_shell_watch_link",
|
|
338
|
-
"reference": "references/watch-link-handoff.md",
|
|
339
|
-
"requires": [
|
|
340
|
-
"campaignId",
|
|
341
|
-
"watchUrl",
|
|
342
|
-
"campaignBrief"
|
|
343
|
-
],
|
|
344
|
-
"requiredVisibleContent": [
|
|
345
|
-
"draft campaign shell",
|
|
346
|
-
"brief is already there",
|
|
347
|
-
"watch it fill in",
|
|
348
|
-
"no leads import and nothing sends yet",
|
|
349
|
-
"Watch link:"
|
|
350
|
-
],
|
|
351
|
-
"requiresCampaignState": [
|
|
352
|
-
"campaignId",
|
|
353
|
-
"watchUrl",
|
|
354
|
-
"campaignBrief"
|
|
355
|
-
],
|
|
356
192
|
"watchUrlSource": "create_campaign.watchUrl",
|
|
357
193
|
"requiredWatchUrlShape": "direct /campaign-builder/{campaignId}?mode={claude|codex} watch URL with token auto-login and workspace routing",
|
|
194
|
+
"immediateNextMainChatLine": "Cool, let's find leads.",
|
|
358
195
|
"codexBrowserHandoff": {
|
|
359
196
|
"openWhenAvailable": false,
|
|
360
197
|
"printWatchLinkOnly": true,
|
|
361
198
|
"tellUserCommandEnterOrClick": true,
|
|
362
199
|
"mustNotUseBrowserAutomation": true,
|
|
363
|
-
"fallbackMustNotClaimInspection": true
|
|
364
|
-
|
|
365
|
-
},
|
|
366
|
-
"immediateNextMainChatLine": "Cool, let's find leads."
|
|
200
|
+
"fallbackMustNotClaimInspection": true
|
|
201
|
+
}
|
|
367
202
|
}
|
|
368
203
|
],
|
|
369
|
-
"requiredArtifacts": [],
|
|
370
|
-
"producesArtifacts": [],
|
|
371
204
|
"allowedTools": [
|
|
372
205
|
"get_subskill_prompt",
|
|
373
|
-
"get_subskill_asset",
|
|
374
|
-
"get_auth_status",
|
|
375
|
-
"get_active_workspace",
|
|
376
|
-
"complete_sender_research",
|
|
377
206
|
"fetch_company",
|
|
378
207
|
"fetch_company_posts",
|
|
379
208
|
"fetch_linkedin_profile",
|
|
380
209
|
"fetch_linkedin_posts",
|
|
210
|
+
"complete_sender_research",
|
|
381
211
|
"create_campaign",
|
|
382
|
-
"update_campaign",
|
|
383
|
-
"WebFetch",
|
|
384
|
-
"WebSearch",
|
|
385
212
|
"AskUserQuestion",
|
|
386
213
|
"request_user_input"
|
|
387
214
|
],
|
|
388
215
|
"doNotAllow": [
|
|
216
|
+
"list_senders",
|
|
389
217
|
"save_rubrics",
|
|
390
218
|
"import_leads",
|
|
391
219
|
"confirm_lead_list",
|
|
392
220
|
"queue_cells",
|
|
393
|
-
"start_campaign"
|
|
394
|
-
"enrich_with_prospeo",
|
|
395
|
-
"bulk_enrich_with_prospeo"
|
|
221
|
+
"start_campaign"
|
|
396
222
|
],
|
|
397
|
-
"watchRequired": false,
|
|
398
223
|
"waitFor": [
|
|
399
|
-
"brief_ready",
|
|
400
224
|
"campaign_shell_created",
|
|
225
|
+
"brief_ready",
|
|
401
226
|
"confirm_with_user"
|
|
402
227
|
],
|
|
403
228
|
"transitions": {
|
|
229
|
+
"campaign_shell_created": "brief-review",
|
|
404
230
|
"brief_ready": "brief-review",
|
|
405
|
-
"confirm_with_user": "brief-review"
|
|
406
|
-
|
|
407
|
-
},
|
|
408
|
-
"optionalProducesArtifacts": [
|
|
409
|
-
"lead-source-intake.json"
|
|
410
|
-
],
|
|
411
|
-
"debugProducesArtifacts": [
|
|
412
|
-
"brief.md",
|
|
413
|
-
"campaign-shell.json"
|
|
414
|
-
]
|
|
231
|
+
"confirm_with_user": "brief-review"
|
|
232
|
+
}
|
|
415
233
|
},
|
|
416
234
|
{
|
|
417
235
|
"id": "brief-review",
|
|
418
236
|
"label": "Brief review",
|
|
419
237
|
"onEnter": [
|
|
420
238
|
{
|
|
421
|
-
"action": "
|
|
422
|
-
"
|
|
423
|
-
"fallbackDebugArtifact": "brief.md"
|
|
424
|
-
},
|
|
425
|
-
{
|
|
426
|
-
"action": "render_brief_approval_checkpoint",
|
|
427
|
-
"requiredVisibleContent": [
|
|
428
|
-
"Campaign brief",
|
|
429
|
-
"Who we are targeting",
|
|
430
|
-
"Why they should care",
|
|
431
|
-
"Offer / CTA",
|
|
432
|
-
"Proof to use",
|
|
433
|
-
"Lead source hypothesis",
|
|
434
|
-
"Message angle",
|
|
435
|
-
"Risks / assumptions",
|
|
436
|
-
"What happens next",
|
|
437
|
-
"approve this brief",
|
|
438
|
-
"revise the brief",
|
|
439
|
-
"then I will find good-fit leads"
|
|
440
|
-
],
|
|
441
|
-
"minimumVisibleBriefDetail": "full_readable_brief_before_question",
|
|
442
|
-
"forbiddenSubstituteApprovalSurface": "Do not replace the visible brief with a summary like `the brief is visible there`; the user must see the actual campaign brief content in chat before the approval question.",
|
|
443
|
-
"requiredCampaignLinks": [
|
|
444
|
-
"watchUrl"
|
|
445
|
-
],
|
|
446
|
-
"campaignLinkTiming": "before_approval_question",
|
|
447
|
-
"questionToolGate": "Do not call AskUserQuestion or request_user_input for brief approval until the immediately preceding customer-visible chat text includes `Watch link:` with the create_campaign.watchUrl for this campaign shell.",
|
|
448
|
-
"missingWatchLinkRecovery": "If the brief approval question would appear before the watch link, stop and send the rendered brief checkpoint plus `Watch link: {watchUrl}` first; then ask the approve/revise question.",
|
|
449
|
-
"forbiddenNormalCustomerLinks": [
|
|
450
|
-
"brief.md",
|
|
451
|
-
"local draft path",
|
|
452
|
-
"Open artifact:"
|
|
453
|
-
],
|
|
454
|
-
"avoidQuestionWhenOnlyUsefulAnswerIs": "looks good"
|
|
455
|
-
},
|
|
456
|
-
{
|
|
457
|
-
"action": "ask_continue_or_revise_only_if_needed",
|
|
458
|
-
"requiresPriorVisibleContent": [
|
|
459
|
-
"full readable brief",
|
|
460
|
-
"live campaign shell orientation",
|
|
461
|
-
"Watch link: {watchUrl}"
|
|
462
|
-
],
|
|
463
|
-
"mustNotCallQuestionToolUntil": "The watch link has already been shown in normal chat text after create_campaign returned watchUrl.",
|
|
464
|
-
"autoContinueWhen": {
|
|
465
|
-
"artifactStatus": "confirmed",
|
|
466
|
-
"confidenceIn": [
|
|
467
|
-
"high",
|
|
468
|
-
"medium"
|
|
469
|
-
],
|
|
470
|
-
"noOpenStrategicTradeoff": true,
|
|
471
|
-
"noMissingRequiredInputs": true
|
|
472
|
-
}
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
"action": "optional_debug_artifact_sync",
|
|
476
|
-
"artifacts": [
|
|
477
|
-
"brief.md"
|
|
478
|
-
],
|
|
479
|
-
"debugOrUatOnly": true,
|
|
480
|
-
"requiredBeforeTransition": false,
|
|
481
|
-
"reconcileRule": "If debug/UAT artifacts are enabled, verify the sidecar persisted the same brief shown in chat. Normal customer Find Leads work reads CampaignOffer.campaignBrief, not brief.md.",
|
|
482
|
-
"chatRenderRule": "Do not block the brief approval question or find-leads transition on this step. Only mention artifact persistence if debug/UAT mode fails or the user asks."
|
|
239
|
+
"action": "render_brief_inline",
|
|
240
|
+
"minimumVisibleDetail": "campaign direction, buyer, offer, proof, source plan, safety gates"
|
|
483
241
|
},
|
|
484
242
|
{
|
|
485
|
-
"action": "
|
|
486
|
-
"
|
|
487
|
-
"
|
|
488
|
-
"
|
|
489
|
-
"
|
|
490
|
-
|
|
491
|
-
"when": "after_user_brief_confirmed_or_auto_continue",
|
|
492
|
-
"fields": [
|
|
493
|
-
"campaignBrief",
|
|
494
|
-
"currentStep:pick-provider",
|
|
495
|
-
"watchNarration: find-leads with the first provider/lane being tested"
|
|
496
|
-
],
|
|
497
|
-
"fallback": "If campaignId is missing from CampaignOffer state, stop; shell-first flow requires an existing campaign before sourcing leads.",
|
|
498
|
-
"readsCampaignStateFirst": true,
|
|
499
|
-
"debugArtifacts": [
|
|
500
|
-
"campaign-shell.json",
|
|
501
|
-
"brief.md"
|
|
243
|
+
"action": "ask_brief_choice",
|
|
244
|
+
"uses": "request_user_input",
|
|
245
|
+
"choices": [
|
|
246
|
+
"Approve brief",
|
|
247
|
+
"Revise brief",
|
|
248
|
+
"Pause here"
|
|
502
249
|
]
|
|
503
250
|
}
|
|
504
251
|
],
|
|
505
|
-
"
|
|
506
|
-
|
|
252
|
+
"requiredCampaignState": [
|
|
253
|
+
"campaignId",
|
|
254
|
+
"watchUrl",
|
|
255
|
+
"campaignBrief",
|
|
256
|
+
"currentStep"
|
|
257
|
+
],
|
|
507
258
|
"allowedTools": [
|
|
508
259
|
"AskUserQuestion",
|
|
509
260
|
"request_user_input",
|
|
510
|
-
"get_subskill_prompt",
|
|
511
261
|
"update_campaign"
|
|
512
262
|
],
|
|
513
263
|
"doNotAllow": [
|
|
514
264
|
"create_campaign",
|
|
515
|
-
"
|
|
265
|
+
"list_senders",
|
|
516
266
|
"import_leads",
|
|
517
267
|
"confirm_lead_list",
|
|
518
268
|
"queue_cells",
|
|
519
|
-
"start_campaign"
|
|
520
|
-
"enrich_with_prospeo",
|
|
521
|
-
"bulk_enrich_with_prospeo"
|
|
269
|
+
"start_campaign"
|
|
522
270
|
],
|
|
523
|
-
"watchRequired": false,
|
|
524
271
|
"waitFor": [
|
|
525
272
|
"user_brief_confirmed",
|
|
526
273
|
"revise_brief",
|
|
@@ -530,13 +277,7 @@
|
|
|
530
277
|
"user_brief_confirmed": "find-leads",
|
|
531
278
|
"revise_brief": "brief-interview",
|
|
532
279
|
"auto_continue": "find-leads"
|
|
533
|
-
}
|
|
534
|
-
"interruptOnly": true,
|
|
535
|
-
"requiredCampaignState": [
|
|
536
|
-
"campaignId",
|
|
537
|
-
"campaignBrief",
|
|
538
|
-
"currentStep"
|
|
539
|
-
]
|
|
280
|
+
}
|
|
540
281
|
},
|
|
541
282
|
{
|
|
542
283
|
"id": "find-leads",
|
|
@@ -552,26 +293,8 @@
|
|
|
552
293
|
"people engaging with relevant LinkedIn posts",
|
|
553
294
|
"Sales Nav to find ICP people actively posting on LinkedIn",
|
|
554
295
|
"search by titles",
|
|
555
|
-
"Prospeo for a broader account/contact path
|
|
296
|
+
"Prospeo for a broader account/contact path"
|
|
556
297
|
],
|
|
557
|
-
"sourceDirectionOverrides": {
|
|
558
|
-
"postEngagement": "signal-discovery",
|
|
559
|
-
"creatorOrCommentSignals": "signal-discovery",
|
|
560
|
-
"titlePersonaCompanyFilters": "sales-nav",
|
|
561
|
-
"hiringSignals": "prospeo",
|
|
562
|
-
"companyGrowthTriggers": "prospeo",
|
|
563
|
-
"targetAccountsOrDomains": "prospeo",
|
|
564
|
-
"suppliedProfilesOrCsv": "supplied-list",
|
|
565
|
-
"explicitCompare": "compare-requested-sources"
|
|
566
|
-
},
|
|
567
|
-
"quickViabilityRule": "Run only enough of the current lane to decide whether it can supply relevant, reachable ICP-looking leads. For Signals, viability requires sampled ICP-fit rate normalized to good-fit prospects per 100 engagers, required engagers to scrape, average reachable engagers per right-content post, projected good-fit prospects per post after cleanup, and posts-needed math against the 300-good-fit source target, not raw post count or the 15-row review-batch import limit. Stop on the first viable source unless the user asked for comparison.",
|
|
568
|
-
"sourceFailureHandling": [
|
|
569
|
-
"timeout/error: try the next approved lane or ask the user to revise the source/target before import",
|
|
570
|
-
"zero raw results: try the next approved lane or ask the user to revise the source/target before import",
|
|
571
|
-
"weak ICP fit: try the next approved lane or ask the user to revise the source/target before import",
|
|
572
|
-
"weak message context: try the next approved lane or ask the user to revise the source/target before import"
|
|
573
|
-
],
|
|
574
|
-
"allLanesFailedState": "revise-source",
|
|
575
298
|
"parallelAllowedOnlyWhen": [
|
|
576
299
|
"user explicitly requested source comparison",
|
|
577
300
|
"resuming already-started parallel scouts",
|
|
@@ -580,134 +303,60 @@
|
|
|
580
303
|
},
|
|
581
304
|
"onEnter": [
|
|
582
305
|
{
|
|
583
|
-
"action": "advance_watch_to_source_selection",
|
|
584
306
|
"tool": "update_campaign",
|
|
585
|
-
"requiredFields": [
|
|
586
|
-
"campaignId",
|
|
587
|
-
"currentStep",
|
|
588
|
-
"watchNarration"
|
|
589
|
-
],
|
|
590
307
|
"requiredValues": {
|
|
591
308
|
"currentStep": "pick-provider",
|
|
592
309
|
"watchNarration.stage": "find-leads"
|
|
593
310
|
},
|
|
594
|
-
"
|
|
595
|
-
"requiresVisibleCheckpointBeforeProviderLane": true,
|
|
596
|
-
"askApprovalBeforeFirstLane": true,
|
|
597
|
-
"forbidDirectPlanToProviderLane": true,
|
|
598
|
-
"chatRenderRule": "Move the campaign watch view to the Pick Provider step before the main thread starts source viability work. This must be a distinct visible checkpoint: do not jump directly from Plan to Signal Discovery, Sales Nav, Prospeo, or another provider lane in the same visible beat. While the watched browser is on Pick Provider, explain the source-selection logic and ask for approval before starting Signal Discovery or a user-directed first lane. If the user did not specify a source, explain the default order in plain language: people engaging with relevant LinkedIn posts, then Sales Nav to find ICP people actively posting on LinkedIn, then search by titles, then Prospeo for a broader account/contact path. Keep the legacy provider mapping clear: Signal Discovery first, then Sales Nav with recent activity, then broader Sales Nav, and Prospeo only as the fallback. If starting with Signal Discovery, explicitly say this is a viability test: Codex will look for relevant posts, sample engagers, estimate ICP fit, and only continue if the source math works. If the user did specify hiring signals, domains/accounts, supplied lists, posts/comments, or titles/personas, explain that the matching source overrides the default funnel and still needs user approval before the lane starts. State that no leads import until a source is approved. The watchNarration headline/body must name the first lane being considered, why this lane now, the quick viability gate, and the safety boundary. Do not mention MCP or local artifacts."
|
|
599
|
-
},
|
|
600
|
-
{
|
|
601
|
-
"action": "advance_watch_to_initial_source_lane",
|
|
602
|
-
"tool": "update_campaign",
|
|
603
|
-
"requiredFields": [
|
|
604
|
-
"campaignId",
|
|
605
|
-
"currentStep",
|
|
606
|
-
"watchNarration"
|
|
607
|
-
],
|
|
608
|
-
"currentStepByPrimaryLane": {
|
|
609
|
-
"signals": "signal-discovery",
|
|
610
|
-
"salesNav": "sales-nav",
|
|
611
|
-
"prospeo": "prospeo",
|
|
612
|
-
"apollo": "apollo-ai",
|
|
613
|
-
"existingList": "saved-lists",
|
|
614
|
-
"uploadedDomains": "prospeo"
|
|
615
|
-
},
|
|
616
|
-
"when": "after_source_selection_checkpoint_before_first_source_attempt",
|
|
617
|
-
"requiresPriorVisibleStep": "pick-provider",
|
|
618
|
-
"rule": "Choose the first visible source lane from explicit source direction when present, otherwise default to Signal Discovery. Only run this after the Pick Provider source-selection checkpoint has been made visible and explained in chat/watchNarration. Send watchNarration with stage find-leads that says why this lane is being tried now, what quick sample or filter gate will pass/fail it, and why that helps this campaign. For Signal Discovery sampling, make it clear this is a viability path before lead import: generate intersection-first keyword lanes that combine the campaign anchor with the buyer pain/use case/ICP role, not broad anchor-only lanes. For Claude/GTM campaigns, prefer lanes like Claude outbound, Claude Code LinkedIn outreach, AI SDR Claude, GTM automation Claude, and founder-led sales Claude over generic Claude Code, MCP, AI agents, or agentic coding. If the first pass is broad, retarget around the campaign wedge before selecting posts. Promote/select the first narrow sample posts with select_promising_posts before fetch_post_engagers so the watched table shows the exact posts being sampled; the guide copy should say Codex is pulling sample engagers from these posts to confirm the ICP is actually engaging and estimate whether enough right-content posts exist for the 300-good-fit source target. Before final source approval, compute eligible posts, sampled ICP-fit rate, good-fit prospects per 100 engagers, required engagers to scrape, average reachable engagers per right-content post, expected good-fit prospects per post after cleanup, source target good-fit lead count, posts needed, selected posts, expected good-fit range, and scale fallback. If the lane fails, update currentStep and watchNarration before moving to Sales Nav recent activity, normal Sales Nav, or Prospeo."
|
|
619
|
-
},
|
|
620
|
-
{
|
|
621
|
-
"action": "run_first_campaign_attached_source_search",
|
|
622
|
-
"requiredFields": [
|
|
623
|
-
"campaignOfferId",
|
|
624
|
-
"currentStep"
|
|
625
|
-
],
|
|
626
|
-
"before": "evaluating_source_viability_gate",
|
|
627
|
-
"rule": "The parent thread must run the campaign-attached provider prompt + provider search for the current visible lane with campaignOfferId and currentStep (signal-discovery, sales-nav, prospeo, or the user-directed lane) so the campaign UI creates the corresponding live search/tab. Do not wait on background scouts before the user sees the active lane. Run only enough evidence to pass/fail this lane, then either recommend it or update the visible lane before trying the next fallback."
|
|
628
|
-
},
|
|
629
|
-
{
|
|
630
|
-
"action": "render_find_leads_progress",
|
|
631
|
-
"requiredVisibleContent": [
|
|
632
|
-
"good fit and active enough to be worth a LinkedIn test",
|
|
633
|
-
"campaign source step",
|
|
634
|
-
"primary source",
|
|
635
|
-
"source hypothesis",
|
|
636
|
-
"why this source now",
|
|
637
|
-
"quick viability gate",
|
|
638
|
-
"expected volume",
|
|
639
|
-
"sampled ICP fit",
|
|
640
|
-
"activity/warmth signal",
|
|
641
|
-
"cleanup risk",
|
|
642
|
-
"tradeoffs",
|
|
643
|
-
"search lanes",
|
|
644
|
-
"timeframe",
|
|
645
|
-
"sample size",
|
|
646
|
-
"estimated usable leads",
|
|
647
|
-
"source decision + sample",
|
|
648
|
-
"no import or enrichment yet"
|
|
649
|
-
],
|
|
650
|
-
"watchNarrationRule": "Do not include time estimates. Use current, campaign-specific search reasoning instead."
|
|
651
|
-
},
|
|
652
|
-
{
|
|
653
|
-
"action": "read_optional_source_intake",
|
|
654
|
-
"artifact": "lead-source-intake.json",
|
|
655
|
-
"sourceTypes": [
|
|
656
|
-
"normal-discovery",
|
|
657
|
-
"supplied-linkedin-profiles",
|
|
658
|
-
"supplied-domains",
|
|
659
|
-
"existing-lead-list"
|
|
660
|
-
],
|
|
661
|
-
"pastedInput": "normalize up to 100 LinkedIn profile URLs or domains into a temporary local CSV before preview"
|
|
311
|
+
"purpose": "show the visible source-selection checkpoint before provider lanes"
|
|
662
312
|
},
|
|
663
313
|
{
|
|
664
|
-
"
|
|
665
|
-
"
|
|
666
|
-
"mode": "campaign-attached-required",
|
|
667
|
-
"sourceScoutRule": "Shell-first flow requires the CampaignOffer campaignId from durable state. Pass campaignId as campaignOfferId into every provider prompt/search that can persist source state (`get_provider_prompt({ provider, campaignOfferId, confirmed: true })`, `search_signals`, `search_sales_nav`, `search_prospeo`) and include currentStep for tools that accept it so the user can watch the selected source inside the campaign. Use the default sequential source viability funnel when the user did not specify a source: Signal Discovery first, then Sales Nav with recent activity, then general Sales Nav, then Prospeo only as fallback. For Signal Discovery, use intersection-first keyword lanes that combine the campaign anchor with the buyer pain/use case/ICP role; broad anchor-only lanes are fallback inventory, not selectable source lanes while narrower wedge lanes exist. Do not recommend from raw post count; sample engagers, calculate ICP-fit rate, good-fit prospects per 100 engagers, required engagers to scrape, average reachable engagers per right-content post, expected good-fit prospects per post after cleanup, source target good-fit lead count (default 300), posts needed, selected posts, expected good-fit range, and scale fallback. For Sales Nav fallback, do not over-tighten filters into a tiny pool; if preview/projected usable volume is below the target, loosen nonessential filters before presenting Sales Nav as the scale option and label it constrained if it still cannot reach the target. Stop on the first viable source unless the user explicitly asked to compare. If the user names hiring signals, domains/accounts, supplied lists, posts/comments, or title/persona filters, start with the matching source instead. Parallel source scouts only when the user requested comparison, an existing parallel run is being resumed, or the first viable source is borderline and one cheap fallback check is needed. The later import_leads call must use the same campaignOfferId and, for Signal Discovery, targetEngagerCount from the approved math so it does not scrape every selected sample post by default. Do not import, confirm, enrich, queue, or start leads during source discovery."
|
|
314
|
+
"tool": "get_source_scout_registry",
|
|
315
|
+
"purpose": "load canonical source scout names before optional branch launch"
|
|
668
316
|
},
|
|
669
317
|
{
|
|
670
|
-
"action": "
|
|
671
|
-
"
|
|
672
|
-
"
|
|
673
|
-
"
|
|
318
|
+
"action": "run_sequential_source_funnel",
|
|
319
|
+
"defaultOrder": [
|
|
320
|
+
"source-scout-linkedin-engagement",
|
|
321
|
+
"source-scout-sales-nav",
|
|
322
|
+
"source-scout-prospeo-contact"
|
|
674
323
|
],
|
|
675
|
-
"
|
|
676
|
-
"
|
|
677
|
-
"chatRenderRule": "Do not create or surface local lead-review artifacts in normal customer runs. The main thread renders the source decision in chat and persists provider/source state to the campaign."
|
|
324
|
+
"campaignOfferIdRequired": true,
|
|
325
|
+
"stopOnFirstViableUnlessComparisonRequested": true
|
|
678
326
|
}
|
|
679
327
|
],
|
|
680
|
-
"
|
|
681
|
-
|
|
328
|
+
"requiredCampaignState": [
|
|
329
|
+
"campaignId",
|
|
330
|
+
"campaignBrief",
|
|
331
|
+
"currentStep"
|
|
332
|
+
],
|
|
682
333
|
"allowedTools": [
|
|
683
|
-
"
|
|
684
|
-
"get_subskill_asset",
|
|
334
|
+
"get_source_scout_registry",
|
|
685
335
|
"get_provider_prompt",
|
|
686
336
|
"lookup_sales_nav_filter",
|
|
687
337
|
"search_sales_nav",
|
|
688
338
|
"search_prospeo",
|
|
689
339
|
"search_signals",
|
|
340
|
+
"select_promising_posts",
|
|
690
341
|
"fetch_post_engagers",
|
|
691
342
|
"fetch_company",
|
|
692
343
|
"fetch_linkedin_profile",
|
|
693
|
-
"AskUserQuestion",
|
|
694
|
-
"request_user_input",
|
|
695
344
|
"load_csv_linkedin_leads",
|
|
696
345
|
"load_csv_domains",
|
|
697
346
|
"get_rows_minimal",
|
|
698
|
-
"update_campaign"
|
|
347
|
+
"update_campaign",
|
|
348
|
+
"AskUserQuestion",
|
|
349
|
+
"request_user_input"
|
|
699
350
|
],
|
|
700
351
|
"doNotAllow": [
|
|
701
352
|
"create_campaign",
|
|
353
|
+
"list_senders",
|
|
702
354
|
"save_rubrics",
|
|
703
355
|
"import_leads",
|
|
704
356
|
"confirm_lead_list",
|
|
705
357
|
"queue_cells",
|
|
706
|
-
"start_campaign"
|
|
707
|
-
"enrich_with_prospeo",
|
|
708
|
-
"bulk_enrich_with_prospeo"
|
|
358
|
+
"start_campaign"
|
|
709
359
|
],
|
|
710
|
-
"watchRequired": false,
|
|
711
360
|
"waitFor": [
|
|
712
361
|
"lead_review_ready",
|
|
713
362
|
"revise_brief",
|
|
@@ -717,220 +366,54 @@
|
|
|
717
366
|
"lead_review_ready": "lead-review",
|
|
718
367
|
"revise_brief": "brief-interview",
|
|
719
368
|
"confirm_with_user": "lead-review"
|
|
720
|
-
}
|
|
721
|
-
"optionalRequiredArtifacts": [
|
|
722
|
-
"lead-source-intake.json"
|
|
723
|
-
],
|
|
724
|
-
"toolRules": {
|
|
725
|
-
"suppliedLinkedinProfiles": "Preview only before the bounded import step. campaignOfferId may attach the preview/list choice to campaign state, but do not import into the campaign table until auto-execute-leads confirms the source list.",
|
|
726
|
-
"suppliedDomains": "May confirm load_csv_domains to produce a domainFilterId. Campaign-associated Prospeo preview searches must use campaignOfferId so the user can watch source state in the campaign, but no import/enrichment happens until rubrics and message set are ready.",
|
|
727
|
-
"existingLeadList": "Sample existing rows before import; preserve the existing list as selectedLeadListId source state and do not clone/import until auto-execute-leads.",
|
|
728
|
-
"forbiddenPreImport": [
|
|
729
|
-
"import_leads",
|
|
730
|
-
"confirm_lead_list",
|
|
731
|
-
"queue_cells",
|
|
732
|
-
"enrich_with_prospeo",
|
|
733
|
-
"bulk_enrich_with_prospeo",
|
|
734
|
-
"start_campaign",
|
|
735
|
-
"save_domain_filters"
|
|
736
|
-
],
|
|
737
|
-
"providerCampaignOfferIdRequiredFor": [
|
|
738
|
-
"get_provider_prompt",
|
|
739
|
-
"search_signals",
|
|
740
|
-
"search_sales_nav",
|
|
741
|
-
"search_prospeo",
|
|
742
|
-
"import_leads",
|
|
743
|
-
"selected source state"
|
|
744
|
-
]
|
|
745
|
-
},
|
|
746
|
-
"requiredCampaignState": [
|
|
747
|
-
"campaignId",
|
|
748
|
-
"campaignBrief",
|
|
749
|
-
"currentStep"
|
|
750
|
-
],
|
|
751
|
-
"debugProducesArtifacts": [
|
|
752
|
-
"lead-review.md",
|
|
753
|
-
"lead-sample.json"
|
|
754
|
-
]
|
|
369
|
+
}
|
|
755
370
|
},
|
|
756
371
|
{
|
|
757
372
|
"id": "lead-review",
|
|
758
|
-
"label": "
|
|
373
|
+
"label": "Source approval",
|
|
759
374
|
"onEnter": [
|
|
760
375
|
{
|
|
761
|
-
"action": "
|
|
762
|
-
"
|
|
763
|
-
|
|
764
|
-
"
|
|
765
|
-
"
|
|
766
|
-
"Math",
|
|
767
|
-
"Eligible posts",
|
|
768
|
-
"Sample",
|
|
769
|
-
"ICP-fit",
|
|
770
|
-
"Good-fit / 100 engagers",
|
|
771
|
-
"Required engagers",
|
|
772
|
-
"Avg engagers/post",
|
|
773
|
-
"Good-fit / post",
|
|
774
|
-
"Source target",
|
|
775
|
-
"Posts needed",
|
|
776
|
-
"Selected",
|
|
777
|
-
"Review batch",
|
|
778
|
-
"Expected good-fit leads",
|
|
779
|
-
"Scale option",
|
|
780
|
-
"Why this source"
|
|
781
|
-
],
|
|
782
|
-
"signalsFirstRequiredFields": [
|
|
783
|
-
"post URL",
|
|
784
|
-
"post author",
|
|
785
|
-
"posted date or recency",
|
|
786
|
-
"topic or excerpt",
|
|
787
|
-
"engagement or estimated engagers",
|
|
788
|
-
"sampled engagers",
|
|
789
|
-
"sampled fits",
|
|
790
|
-
"sampled fits as n/N",
|
|
791
|
-
"estimated usable leads",
|
|
792
|
-
"why use or discard"
|
|
793
|
-
],
|
|
794
|
-
"evidenceSnapshotRequiredFields": [
|
|
795
|
-
"provider/source angle label",
|
|
796
|
-
"source lane or keyword",
|
|
797
|
-
"timeframe searched",
|
|
798
|
-
"raw results found",
|
|
799
|
-
"finalist posts or preview rows reviewed",
|
|
376
|
+
"action": "show_source_decision_card",
|
|
377
|
+
"requiredInlineFields": [
|
|
378
|
+
"primary source and exact filters/recipe",
|
|
379
|
+
"runner-up and why it lost",
|
|
380
|
+
"raw volume",
|
|
800
381
|
"sampled people",
|
|
801
|
-
"sampled fits as n/N plus percentage
|
|
802
|
-
"estimated usable
|
|
803
|
-
"
|
|
804
|
-
"
|
|
805
|
-
]
|
|
806
|
-
"sourceDecisionRequiredFields": [
|
|
807
|
-
"primary source",
|
|
808
|
-
"exact Sales Nav filters or source recipe",
|
|
809
|
-
"runner-up source",
|
|
810
|
-
"why runner-up lost",
|
|
811
|
-
"what approval means"
|
|
812
|
-
],
|
|
813
|
-
"approvalMathRequiredFields": [
|
|
814
|
-
"selected or relevant posts count",
|
|
815
|
-
"eligible right-content posts count",
|
|
816
|
-
"reachable engagers count",
|
|
817
|
-
"sampled engagers count",
|
|
818
|
-
"sampled ICP fits as n/N plus percentage or range",
|
|
819
|
-
"good-fit prospects per 100 engagers",
|
|
820
|
-
"required engagers to scrape",
|
|
821
|
-
"average reachable engagers per post",
|
|
822
|
-
"expected good-fit prospects per post after cleanup",
|
|
823
|
-
"dedupe or cleanup factor",
|
|
824
|
-
"source target good-fit lead count default 300",
|
|
825
|
-
"posts needed for target",
|
|
826
|
-
"selected posts count",
|
|
827
|
-
"15-row review-batch import limit",
|
|
828
|
-
"estimated usable prospects range",
|
|
829
|
-
"scale alternative source",
|
|
830
|
-
"scale alternative raw or preview volume",
|
|
831
|
-
"scale alternative sampled usable rows as n/N plus percentage or range",
|
|
832
|
-
"Sales Nav broadening or loosening attempts when fallback volume is too tight",
|
|
833
|
-
"warmth or message-context tradeoff",
|
|
834
|
-
"what to choose if the user wants more volume"
|
|
835
|
-
],
|
|
836
|
-
"signalsInlineTableRequiredFields": [
|
|
837
|
-
"keyword lane",
|
|
838
|
-
"timeframe",
|
|
839
|
-
"posts found",
|
|
840
|
-
"finalist posts reviewed",
|
|
841
|
-
"post URL or title",
|
|
842
|
-
"engagers or engagement count",
|
|
843
|
-
"sampled engagers",
|
|
844
|
-
"good fits as n/N",
|
|
845
|
-
"estimated usable prospects per post",
|
|
846
|
-
"use or discard decision"
|
|
847
|
-
],
|
|
848
|
-
"forbidPercentOnlyFitRates": true,
|
|
849
|
-
"requiredArtifactLinks": [
|
|
850
|
-
"lead-review.md"
|
|
851
|
-
],
|
|
852
|
-
"artifactLinkTiming": "before_next_step_or_revision_question",
|
|
853
|
-
"doNotCompressToSummaryOnly": false,
|
|
854
|
-
"doNotRenderArtifactLinksOnly": true,
|
|
855
|
-
"sourceRecommendationReadyWatchRule": "When the source recommendation decision card is ready in chat with counts and sample quality, and before asking for source approval, call update_campaign with leadSourceType `new`, leadSourceProvider set to the recommended primary provider, currentStep set to that provider lane (`sales-nav`, `signal-discovery`, or `prospeo`), and find-leads watchNarration. If the recommendation changed from the lane last sampled, switch the watched provider page to the recommended lane first so the user can inspect what they are approving. Use a headline like `Review the source in Codex`, body copy that says the browser is showing the evaluated source/results, and nextAction like `Approve in Codex`. Do not keep future-tense copy like `I'll show a source recommendation` after the decision is visible. Include a safety note that no leads import until the user approves the source.",
|
|
856
|
-
"chatRenderRule": "Show a compact rendered-Markdown decision card only, never a fenced code block. The first sentence must make the decision explicit: 'I recommend {primary source} using {exact filter/source recipe}. The runner-up is {source} because {reason}.' Use only these sections: Lead source decision, Source recommendation, Math, Why this source, and the concrete approval question. The Math section must include labeled lines for Eligible posts, Sample, ICP-fit, Good-fit / 100 engagers, Required engagers, Avg engagers/post, Good-fit / post, Source target, Posts needed, Selected, Review batch, Expected good-fit leads, and Scale option. Show fit as n/N plus an easy percentage or range, never percent-only. Do not include keyword-lane tables, LinkedIn-post-sampled tables, sample-lead lists, or long tradeoff prose in the default approval packet; keep those details in lead-review.md or campaign/source decision state. Do not forecast connection acceptance rates, reply rates, meetings, pipeline, revenue, or ROI unless the user supplied verified benchmark data for this exact workspace/sender. For Signals, do not recommend from raw post count. Compute eligible right-content posts, reachable engagers, sampled ICP-fit rate, good-fit prospects per 100 engagers, required engagers to scrape, average reachable engagers per right-content post, expected good-fit prospects per post after cleanup, source target good-fit lead count defaulting to 300, posts needed, selected posts, expected good-fit range, and scale fallback. Distinguish source-capacity math from the 15-row review-batch import limit. If the selected warm posts only support a review batch or smaller pilot, say they do not hit 300 instead of calling them scalable. If the user wants more volume than the warm post-engagement estimate, explicitly say which Sales Nav or Prospeo alternative provides that volume and what message-context warmth is lost; Sales Nav must be broadened/loosened before it is presented as the scale option if the initial filter pool is too tight. If no engagers could be fetched, say that explicitly and lower confidence. Do not show plain filesystem paths unless links cannot be created."
|
|
857
|
-
},
|
|
858
|
-
{
|
|
859
|
-
"action": "render_post_lead_parallel_progress",
|
|
860
|
-
"requiredVisibleContent": [
|
|
861
|
-
"Lead source is set",
|
|
862
|
-
"campaign is on the primary source step",
|
|
863
|
-
"Tighten the fit filter",
|
|
864
|
-
"Message generation",
|
|
865
|
-
"approved brief and real sample leads",
|
|
866
|
-
"no import or enrichment until rubrics and message set are ready",
|
|
867
|
-
"parallel only if real parallel branches were launched",
|
|
868
|
-
"import the first 15-row review batch before fit/message work",
|
|
869
|
-
"selectedLeadListId stays the source list and workflowTableId is the campaign table"
|
|
870
|
-
],
|
|
871
|
-
"watchNarrationRule": "Do not include time estimates. Say what review-batch work is happening and what the user will approve next.",
|
|
872
|
-
"sourceApprovedImportRule": "After source approval, if chat says import is starting, send review-batch watchNarration with current-tense import copy. Headline should be like `Importing the review batch`; body should say the browser is still showing the approved source leads while only the bounded 15-row review batch is imported. Do not use source-approved or future-tense outcome copy once import is starting.",
|
|
873
|
-
"chatRenderRule": "Lead source is set. Next import and confirm only the first 15-row review batch into the campaign table. After workflowTableId exists, run the fit-filter and message-generation workstreams from the campaign table sample. If real parallel MCP/tool branches or host subagents were actually launched, say so; otherwise say the branches will run sequentially. Never claim parallelism unless parallel execution actually started."
|
|
874
|
-
},
|
|
875
|
-
{
|
|
876
|
-
"action": "ask_continue_revise_or_confirm_only_if_needed",
|
|
877
|
-
"approvalQuestionRule": "If asking the user, the question and options must name the concrete decision. Prefer: 'Approve Sales Nav with {filters}, or use warmer Signals instead?' over 'Approve this lead source?' Option labels must name the source choice, such as 'Approve Sales Nav filters', 'Use warmer Signals posts', 'Try Prospeo/account search', and 'Revise source'.",
|
|
878
|
-
"approvalMathRule": "Immediately above the approval question, render the compact Math block: given this many eligible relevant posts, this many reachable engagers, this sampled ICP fit as n/N plus percentage/range, this many good-fit prospects per 100 engagers, this many required engagers to scrape, this average reachable engagers per post, this expected good-fit prospects per post after cleanup, this source target good-fit lead count defaulting to 300, and this many posts needed, we expect this usable lead range from the selected posts; also state that approval only imports a 15-row campaign review batch first after the source list is materialized. If the user wants more volume, name the Sales Nav or Prospeo alternative, its preview/sample math, any Sales Nav loosening used to avoid an over-tight pool, and the colder/weaker-context tradeoff. Do not ask the approval question until this math is visible.",
|
|
879
|
-
"autoContinueWhen": {
|
|
880
|
-
"status": "confirmed",
|
|
881
|
-
"confidenceIn": [
|
|
882
|
-
"high",
|
|
883
|
-
"medium"
|
|
884
|
-
],
|
|
885
|
-
"projectedGoodFitsAtLeast": 150,
|
|
886
|
-
"samplePassRateAtLeast": 0.7,
|
|
887
|
-
"noProviderMismatch": true,
|
|
888
|
-
"noStrategicTradeoff": true
|
|
889
|
-
}
|
|
382
|
+
"sampled fits as n/N plus percentage/range",
|
|
383
|
+
"estimated usable prospects",
|
|
384
|
+
"cleanup risk",
|
|
385
|
+
"what approval authorizes"
|
|
386
|
+
]
|
|
890
387
|
},
|
|
891
388
|
{
|
|
892
|
-
"action": "
|
|
893
|
-
"
|
|
894
|
-
"
|
|
895
|
-
"
|
|
896
|
-
"
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
"fields": [
|
|
900
|
-
"leadSourceType",
|
|
901
|
-
"leadSourceProvider",
|
|
902
|
-
"providerSearchAssociation",
|
|
903
|
-
"currentStep: primary provider step (signal-discovery, sales-nav, prospeo/contact-search, saved-lists, or leads)",
|
|
904
|
-
"watchNarration: find-leads source recommendation ready, or review-batch import starting when source approval already happened",
|
|
905
|
-
"selectedLeadListId as source list id only for existing-list or supplied-list preview"
|
|
906
|
-
],
|
|
907
|
-
"sourceApprovalWatchRule": "Immediately after the user approves a source, and before lookup_sales_nav_filter, get_provider_prompt, search_sales_nav, search_prospeo, import_leads, or confirm_lead_list, persist the approved source as the active provider on the CampaignOffer. For Sales Nav approval, call update_campaign with leadSourceType `new`, leadSourceProvider `sales-nav`, currentStep `sales-nav`, and current-tense watchNarration so the browser switches off the previous Signal Discovery lane and the user can continue watching the approved provider setup. Apply the same rule for signal-discovery and prospeo approvals.",
|
|
908
|
-
"fallback": "Stop if campaignId is missing; the source must be attached to the existing CampaignOffer before import.",
|
|
909
|
-
"readsCampaignStateFirst": true
|
|
389
|
+
"action": "ask_source_review_choice",
|
|
390
|
+
"uses": "request_user_input",
|
|
391
|
+
"choices": [
|
|
392
|
+
"Approve source",
|
|
393
|
+
"Revise source",
|
|
394
|
+
"Pause here"
|
|
395
|
+
]
|
|
910
396
|
}
|
|
911
397
|
],
|
|
912
|
-
"
|
|
913
|
-
"
|
|
914
|
-
"
|
|
398
|
+
"requiredCampaignState": [
|
|
399
|
+
"campaignId",
|
|
400
|
+
"campaignBrief",
|
|
401
|
+
"providerSearchAssociation"
|
|
915
402
|
],
|
|
916
|
-
"producesArtifacts": [],
|
|
917
403
|
"allowedTools": [
|
|
918
404
|
"AskUserQuestion",
|
|
919
405
|
"request_user_input",
|
|
920
|
-
"get_subskill_prompt",
|
|
921
406
|
"update_campaign"
|
|
922
407
|
],
|
|
923
408
|
"doNotAllow": [
|
|
924
409
|
"create_campaign",
|
|
410
|
+
"list_senders",
|
|
925
411
|
"save_rubrics",
|
|
926
412
|
"import_leads",
|
|
927
413
|
"confirm_lead_list",
|
|
928
414
|
"queue_cells",
|
|
929
|
-
"start_campaign"
|
|
930
|
-
"enrich_with_prospeo",
|
|
931
|
-
"bulk_enrich_with_prospeo"
|
|
415
|
+
"start_campaign"
|
|
932
416
|
],
|
|
933
|
-
"watchRequired": false,
|
|
934
417
|
"waitFor": [
|
|
935
418
|
"lead_review_confirmed",
|
|
936
419
|
"revise_leads",
|
|
@@ -942,184 +425,80 @@
|
|
|
942
425
|
"revise_leads": "find-leads",
|
|
943
426
|
"confirm_with_user": "auto-execute-leads",
|
|
944
427
|
"auto_continue": "auto-execute-leads"
|
|
945
|
-
}
|
|
946
|
-
"interruptOnly": true,
|
|
947
|
-
"requiredCampaignState": [
|
|
948
|
-
"campaignId",
|
|
949
|
-
"campaignBrief",
|
|
950
|
-
"providerSearchAssociation"
|
|
951
|
-
]
|
|
428
|
+
}
|
|
952
429
|
},
|
|
953
430
|
{
|
|
954
431
|
"id": "auto-execute-leads",
|
|
955
|
-
"label": "
|
|
956
|
-
"currentStepValue":
|
|
957
|
-
"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.",
|
|
432
|
+
"label": "Import bounded review batch",
|
|
433
|
+
"currentStepValue": "auto-execute-leads",
|
|
958
434
|
"reference": "references/step-13-import-leads.md",
|
|
959
435
|
"onEnter": [
|
|
960
436
|
{
|
|
961
|
-
"
|
|
962
|
-
"
|
|
963
|
-
|
|
964
|
-
"branches": {
|
|
965
|
-
"normal-discovery": "Reuse the campaign-attached source selections/searches created during find-leads. Do not replay searches in Step 13; if no selected source/search exists, route back to find-leads with campaignOfferId. Provider import materializes the source lead list against the approved source-capacity plan, not the 15-row review batch.",
|
|
966
|
-
"supplied-linkedin-profiles": "Use the campaign-attached preview/list choice. Materialize the CSV into a source lead list when needed, then confirm_lead_list({ sourceLeadListId: leadListId, targetLeadCount: import.importLimit }).",
|
|
967
|
-
"existing-lead-list": "Use the campaign-attached existingLeadListId as selectedLeadListId and call confirm_lead_list({ sourceLeadListId: existingLeadListId, targetLeadCount: import.importLimit }).",
|
|
968
|
-
"supplied-domains": "Reuse the campaign-attached domainFilterId and Prospeo search created during find-leads, then import_leads({ campaignOfferId, targetLeadCount: sourceTargetGoodFitLeadCount default 300 }) to materialize the source list before confirm_lead_list imports the bounded review batch."
|
|
437
|
+
"tool": "get_subskill_prompt",
|
|
438
|
+
"requiredValues": {
|
|
439
|
+
"subskillName": "create-campaign-v2-tail"
|
|
969
440
|
},
|
|
970
|
-
"
|
|
971
|
-
"leadListId",
|
|
972
|
-
"domainFilterId",
|
|
973
|
-
"searchId",
|
|
974
|
-
"selectedLeadListId",
|
|
975
|
-
"workflowTableId",
|
|
976
|
-
"importedRowIds"
|
|
977
|
-
],
|
|
978
|
-
"onSourceFileChanged": "escalate_before_materialization",
|
|
979
|
-
"onLowDomainYield": "confirm-with-user: widen role filters, add more domains, or abort; never drop domainFilterId silently",
|
|
980
|
-
"preconditions": [
|
|
981
|
-
"campaignId exists",
|
|
982
|
-
"providerSearchAssociation or selected source state exists"
|
|
983
|
-
],
|
|
984
|
-
"onMissingCampaignAttachedSource": "stop_before_import_and_route_to_find_leads; source scouts must attach searches/selections with campaignOfferId before Step 13"
|
|
985
|
-
},
|
|
986
|
-
{
|
|
987
|
-
"action": "watch_mode_orient",
|
|
988
|
-
"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."
|
|
441
|
+
"purpose": "load tail contract before execution tools"
|
|
989
442
|
},
|
|
990
443
|
{
|
|
991
444
|
"tool": "import_leads",
|
|
992
|
-
"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.",
|
|
993
|
-
"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.",
|
|
994
445
|
"requiredFields": [
|
|
995
446
|
"campaignOfferId",
|
|
996
|
-
"
|
|
997
|
-
|
|
998
|
-
"targetLeadCountFromConfig": "sourceTargetGoodFitLeadCount (default 300) for provider source-list materialization, not import.importLimit",
|
|
999
|
-
"signalDiscoveryRequiredFields": [
|
|
1000
|
-
"targetEngagerCount from approved source math",
|
|
1001
|
-
"approved promoted post ids selected with select_promising_posts",
|
|
1002
|
-
"maxPostsToScrape from approved source math"
|
|
447
|
+
"selected source/list",
|
|
448
|
+
"importLimit"
|
|
1003
449
|
],
|
|
1004
|
-
"
|
|
1005
|
-
|
|
450
|
+
"requiredValues": {
|
|
451
|
+
"importLimit": 15
|
|
452
|
+
},
|
|
1006
453
|
"modeAddHandshake": {
|
|
1007
|
-
"firstCallReturns": "needsModeSelection
|
|
1008
|
-
"
|
|
1009
|
-
"note": "import_leads with mode=add is a two-step handshake; see references/step-13-import-leads.md"
|
|
454
|
+
"firstCallReturns": "needsModeSelection when adding to an existing campaign-attached list",
|
|
455
|
+
"requiredFollowup": "retry with mode=add after explicit user/source-state compatibility is confirmed"
|
|
1010
456
|
},
|
|
1011
|
-
"surfaceDedupRatio": true
|
|
1012
|
-
"defaultBranch": "normal-discovery",
|
|
1013
|
-
"skipWhen": "resolved source branch returns sourceLeadListId for confirm_lead_list",
|
|
1014
|
-
"requiredBeforeCall": [
|
|
1015
|
-
"campaign_attached_source_state",
|
|
1016
|
-
"for Signal Discovery: approved_promoted_posts_attached_to_campaign"
|
|
1017
|
-
]
|
|
457
|
+
"surfaceDedupRatio": true
|
|
1018
458
|
},
|
|
1019
459
|
{
|
|
1020
|
-
"tool": "wait_for_lead_list_ready"
|
|
1021
|
-
"sourceBranches": [
|
|
1022
|
-
"normal-discovery",
|
|
1023
|
-
"supplied-domains"
|
|
1024
|
-
],
|
|
1025
|
-
"skipWhen": "resolved source branch is supplied-linkedin-profiles or existing-lead-list; direct lead-list branches have no provider import job to wait on and this probe can poison the campaign import status"
|
|
460
|
+
"tool": "wait_for_lead_list_ready"
|
|
1026
461
|
},
|
|
1027
462
|
{
|
|
1028
463
|
"tool": "confirm_lead_list",
|
|
1029
|
-
"
|
|
1030
|
-
|
|
1031
|
-
"normal-discovery",
|
|
1032
|
-
"supplied-domains",
|
|
1033
|
-
"supplied-linkedin-profiles",
|
|
1034
|
-
"existing-lead-list"
|
|
1035
|
-
],
|
|
1036
|
-
"requiredBeforeCall": [
|
|
1037
|
-
"campaign_attached_source_state"
|
|
1038
|
-
],
|
|
1039
|
-
"persists": [
|
|
464
|
+
"requiredFields": [
|
|
465
|
+
"campaignOfferId",
|
|
1040
466
|
"selectedLeadListId",
|
|
1041
|
-
"
|
|
467
|
+
"reviewBatchLimit"
|
|
1042
468
|
],
|
|
1043
|
-
"
|
|
469
|
+
"capture": [
|
|
470
|
+
"workflowTableId",
|
|
471
|
+
"reviewBatchRowIds"
|
|
472
|
+
]
|
|
1044
473
|
},
|
|
1045
474
|
{
|
|
1046
|
-
"tool": "wait_for_campaign_table_ready"
|
|
1047
|
-
"purpose": "wait_for_campaign_table_rows_after_confirm"
|
|
475
|
+
"tool": "wait_for_campaign_table_ready"
|
|
1048
476
|
},
|
|
1049
477
|
{
|
|
1050
478
|
"tool": "get_rows_minimal",
|
|
1051
|
-
"
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
},
|
|
1055
|
-
{
|
|
1056
|
-
"action": "require_non_empty_review_batch_before_filter_choice",
|
|
1057
|
-
"after": "get_rows_minimal",
|
|
1058
|
-
"blocksCurrentStep": "filter-choice",
|
|
1059
|
-
"onZeroRows": "source-import-recovery",
|
|
1060
|
-
"recoveryChoices": [
|
|
1061
|
-
"retry import",
|
|
1062
|
-
"import more from approved source",
|
|
1063
|
-
"revise source"
|
|
1064
|
-
],
|
|
1065
|
-
"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."
|
|
1066
|
-
},
|
|
1067
|
-
{
|
|
1068
|
-
"tool": "get_post_find_leads_scout_registry",
|
|
1069
|
-
"purpose": "load_post_import_message_draft_builder_registry",
|
|
1070
|
-
"requiredBeforeMessageDraftLaunch": true
|
|
1071
|
-
},
|
|
1072
|
-
{
|
|
1073
|
-
"action": "launch_message_draft_builder_after_review_batch_import",
|
|
1074
|
-
"mode": "background_required_when_host_supports_subagents",
|
|
1075
|
-
"registryRequired": "get_post_find_leads_scout_registry",
|
|
1076
|
-
"branch": {
|
|
1077
|
-
"name": "message-generation",
|
|
1078
|
-
"target": "generate-messages",
|
|
1079
|
-
"workerName": "post-find-leads-message-scout",
|
|
1080
|
-
"inputs": [
|
|
1081
|
-
"campaignBrief",
|
|
1082
|
-
"selected source decision",
|
|
1083
|
-
"selectedLeadListId source list",
|
|
1084
|
-
"workflowTableId imported 15-row review batch"
|
|
1085
|
-
],
|
|
1086
|
-
"toolCallRequiredBeforeArtifacts": [
|
|
1087
|
-
"get_subskill_prompt({ subskillName: \"generate-messages\" }) until hasMore=false"
|
|
1088
|
-
],
|
|
1089
|
-
"producesArtifacts": [
|
|
1090
|
-
"template recommendation",
|
|
1091
|
-
"token fill rules",
|
|
1092
|
-
"rendered sample"
|
|
1093
|
-
],
|
|
1094
|
-
"optionalProducesArtifacts": [
|
|
1095
|
-
"message-validation.md",
|
|
1096
|
-
"message-prep.md",
|
|
1097
|
-
"message-candidate-drafts.md"
|
|
1098
|
-
],
|
|
1099
|
-
"ownership": "proof inventory, token strategy, angle drafting, skeptical-prospect review, and selected winner only"
|
|
479
|
+
"requiredValues": {
|
|
480
|
+
"tableId": "{workflowTableId}",
|
|
481
|
+
"limit": 15
|
|
1100
482
|
},
|
|
1101
|
-
"
|
|
1102
|
-
|
|
1103
|
-
|
|
483
|
+
"capture": [
|
|
484
|
+
"reviewBatchRowHash"
|
|
485
|
+
]
|
|
1104
486
|
},
|
|
1105
487
|
{
|
|
1106
|
-
"
|
|
1107
|
-
"
|
|
1108
|
-
|
|
1109
|
-
"currentStep",
|
|
1110
|
-
"watchNarration"
|
|
1111
|
-
],
|
|
1112
|
-
"requiredValues": {
|
|
1113
|
-
"currentStep": "filter-choice",
|
|
1114
|
-
"watchNarration.stage": "fit-message",
|
|
1115
|
-
"watchNarration.headline": "Added to Campaign",
|
|
1116
|
-
"watchNarration.workerStatuses.messageDraftBuilder": "running_after_launch_message_draft_builder_after_review_batch_import_only"
|
|
1117
|
-
},
|
|
1118
|
-
"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."
|
|
488
|
+
"action": "launch_message_draft_builder_after_review_batch_import",
|
|
489
|
+
"tool": "get_post_find_leads_scout_registry",
|
|
490
|
+
"requiresNonEmptyRows": true
|
|
1119
491
|
}
|
|
1120
492
|
],
|
|
493
|
+
"requiredCampaignState": [
|
|
494
|
+
"campaignId",
|
|
495
|
+
"providerSearchAssociation",
|
|
496
|
+
"selectedLeadListId"
|
|
497
|
+
],
|
|
1121
498
|
"allowedTools": [
|
|
499
|
+
"get_subskill_prompt",
|
|
1122
500
|
"get_subskill_asset",
|
|
501
|
+
"get_post_find_leads_scout_registry",
|
|
1123
502
|
"import_leads",
|
|
1124
503
|
"wait_for_lead_list_ready",
|
|
1125
504
|
"confirm_lead_list",
|
|
@@ -1128,70 +507,50 @@
|
|
|
1128
507
|
"update_campaign",
|
|
1129
508
|
"AskUserQuestion",
|
|
1130
509
|
"request_user_input",
|
|
1131
|
-
"load_csv_linkedin_leads",
|
|
1132
|
-
"load_csv_domains",
|
|
1133
|
-
"get_provider_prompt",
|
|
1134
|
-
"get_campaign",
|
|
1135
|
-
"get_post_find_leads_scout_registry",
|
|
1136
|
-
"get_subskill_prompt",
|
|
1137
510
|
"Task",
|
|
1138
511
|
"spawn_agent"
|
|
1139
512
|
],
|
|
1140
513
|
"doNotAllow": [
|
|
514
|
+
"list_senders",
|
|
1141
515
|
"queue_cells",
|
|
1142
516
|
"start_campaign",
|
|
1143
517
|
"enrich_with_prospeo",
|
|
1144
518
|
"bulk_enrich_with_prospeo"
|
|
1145
519
|
],
|
|
1146
|
-
"watchRequired": true,
|
|
1147
520
|
"waitFor": "review_batch_imported",
|
|
1148
521
|
"transitions": {
|
|
1149
522
|
"review_batch_imported": "filter-choice",
|
|
1150
523
|
"escalation_triggered": "escalation"
|
|
1151
|
-
}
|
|
1152
|
-
"requiredArtifacts": [],
|
|
1153
|
-
"requiredCampaignState": [
|
|
1154
|
-
"campaignId",
|
|
1155
|
-
"providerSearchAssociation",
|
|
1156
|
-
"selectedLeadListId"
|
|
1157
|
-
]
|
|
524
|
+
}
|
|
1158
525
|
},
|
|
1159
526
|
{
|
|
1160
527
|
"id": "filter-choice",
|
|
1161
528
|
"label": "Filter choice",
|
|
1162
529
|
"currentStepValue": "filter-choice",
|
|
1163
|
-
"normalFlow": true,
|
|
1164
530
|
"onEnter": [
|
|
1165
|
-
{
|
|
1166
|
-
"action": "show_filter_choice",
|
|
1167
|
-
"requiredVisibleContent": [
|
|
1168
|
-
"Choose filters or skip",
|
|
1169
|
-
"Use filters to keep only qualified leads",
|
|
1170
|
-
"Skip filters and continue to message template review",
|
|
1171
|
-
"active filtering starts only after rubrics and the approved message template are saved"
|
|
1172
|
-
],
|
|
1173
|
-
"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."
|
|
1174
|
-
},
|
|
1175
531
|
{
|
|
1176
532
|
"tool": "update_campaign",
|
|
1177
533
|
"requiredValues": {
|
|
1178
534
|
"currentStep": "filter-choice",
|
|
1179
|
-
"watchNarration.stage": "
|
|
1180
|
-
}
|
|
1181
|
-
"watchNarrationRule": "Ask whether the user wants to further filter the imported leads. Say whether the selected lead list looks mixed/good/noisy based on the imported 15-row review batch, then ask Choose filters or skip. Do not say filtering the batch before rubrics are saved."
|
|
535
|
+
"watchNarration.stage": "filter-choice"
|
|
536
|
+
}
|
|
1182
537
|
},
|
|
1183
538
|
{
|
|
1184
|
-
"action": "
|
|
1185
|
-
"
|
|
1186
|
-
"
|
|
1187
|
-
|
|
1188
|
-
"
|
|
1189
|
-
"
|
|
1190
|
-
|
|
1191
|
-
},
|
|
1192
|
-
"watchNarrationRule": "Move the watched app to Filter Rules and show passive copy that Codex is defining the filters in chat. Do not leave the user on filter-choice after they choose filters."
|
|
539
|
+
"action": "ask_filter_choice",
|
|
540
|
+
"uses": "request_user_input",
|
|
541
|
+
"choices": [
|
|
542
|
+
"Use filters",
|
|
543
|
+
"Skip filters",
|
|
544
|
+
"Revise source"
|
|
545
|
+
]
|
|
1193
546
|
}
|
|
1194
547
|
],
|
|
548
|
+
"requiredCampaignState": [
|
|
549
|
+
"campaignId",
|
|
550
|
+
"campaignBrief",
|
|
551
|
+
"selectedLeadListId",
|
|
552
|
+
"workflowTableId"
|
|
553
|
+
],
|
|
1195
554
|
"allowedTools": [
|
|
1196
555
|
"AskUserQuestion",
|
|
1197
556
|
"request_user_input",
|
|
@@ -1200,16 +559,13 @@
|
|
|
1200
559
|
],
|
|
1201
560
|
"doNotAllow": [
|
|
1202
561
|
"create_campaign",
|
|
1203
|
-
"
|
|
562
|
+
"list_senders",
|
|
1204
563
|
"import_leads",
|
|
1205
564
|
"confirm_lead_list",
|
|
1206
565
|
"queue_cells",
|
|
1207
566
|
"start_campaign",
|
|
1208
|
-
"generate_messages"
|
|
1209
|
-
"enrich_with_prospeo",
|
|
1210
|
-
"bulk_enrich_with_prospeo"
|
|
567
|
+
"generate_messages"
|
|
1211
568
|
],
|
|
1212
|
-
"watchRequired": true,
|
|
1213
569
|
"waitFor": [
|
|
1214
570
|
"filters_enabled",
|
|
1215
571
|
"filters_skipped",
|
|
@@ -1219,189 +575,71 @@
|
|
|
1219
575
|
"filters_enabled": "post-lead-workstreams",
|
|
1220
576
|
"filters_skipped": "message-generation",
|
|
1221
577
|
"revise_leads": "find-leads"
|
|
1222
|
-
}
|
|
1223
|
-
"interruptOnly": true,
|
|
1224
|
-
"requiredCampaignState": [
|
|
1225
|
-
"campaignId",
|
|
1226
|
-
"campaignBrief",
|
|
1227
|
-
"selectedLeadListId",
|
|
1228
|
-
"workflowTableId"
|
|
1229
|
-
]
|
|
578
|
+
}
|
|
1230
579
|
},
|
|
1231
580
|
{
|
|
1232
581
|
"id": "post-lead-workstreams",
|
|
1233
|
-
"label": "
|
|
1234
|
-
"normalFlow": true,
|
|
582
|
+
"label": "Filter and message workstreams",
|
|
1235
583
|
"onEnter": [
|
|
1236
584
|
{
|
|
1237
585
|
"tool": "get_post_find_leads_scout_registry",
|
|
1238
|
-
"
|
|
1239
|
-
"purpose": "Load the canonical two-scout registry before dispatch so Codex and Claude use the same post-find-leads agent names."
|
|
586
|
+
"purpose": "load canonical post-lead worker names"
|
|
1240
587
|
},
|
|
1241
588
|
{
|
|
1242
|
-
"action": "
|
|
589
|
+
"action": "launch_or_reuse_post_lead_workstreams",
|
|
1243
590
|
"mode": "parallel_when_host_supports_subagents",
|
|
1244
|
-
"
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
"selected source decision",
|
|
1252
|
-
"selectedLeadListId",
|
|
1253
|
-
"workflowTableId review-batch rows"
|
|
1254
|
-
],
|
|
1255
|
-
"producesArtifacts": [
|
|
1256
|
-
"lead-filter.md"
|
|
1257
|
-
],
|
|
1258
|
-
"optionalProducesArtifacts": [
|
|
1259
|
-
"rubric.json"
|
|
1260
|
-
],
|
|
1261
|
-
"ownership": "lead quality, false-positive patterns, keep/exclude rules, and production rubric translation only"
|
|
1262
|
-
},
|
|
1263
|
-
{
|
|
1264
|
-
"name": "message-generation",
|
|
1265
|
-
"target": "generate-messages",
|
|
1266
|
-
"inputs": [
|
|
1267
|
-
"campaignBrief",
|
|
1268
|
-
"selected source decision",
|
|
1269
|
-
"selectedLeadListId",
|
|
1270
|
-
"workflowTableId review-batch rows"
|
|
1271
|
-
],
|
|
1272
|
-
"producesArtifacts": [
|
|
1273
|
-
"template recommendation",
|
|
1274
|
-
"token fill rules",
|
|
1275
|
-
"rendered sample"
|
|
1276
|
-
],
|
|
1277
|
-
"optionalProducesArtifacts": [
|
|
1278
|
-
"message-validation.md",
|
|
1279
|
-
"message-prep.md",
|
|
1280
|
-
"message-candidate-drafts.md"
|
|
1281
|
-
],
|
|
1282
|
-
"ownership": "proof inventory, token strategy, angle drafting, skeptical-prospect review, and selected winner only",
|
|
1283
|
-
"mode": "background_template_builder_reuse_or_launch_if_missing",
|
|
1284
|
-
"alreadyStartedBy": "auto-execute-leads.launch_message_draft_builder_after_review_batch_import"
|
|
1285
|
-
}
|
|
1286
|
-
],
|
|
1287
|
-
"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.",
|
|
1288
|
-
"workerStatusContract": "Only show Lead Fit Builder or Message Draft Builder as In Progress when a Task/spawn_agent branch actually started and returned a live branch id, or when the parent-thread fallback is actively doing that branch before the next user-visible step. If a branch is completed in the parent thread, show it as Ready. After update_campaign_brief saves the approved template, Message Draft Builder is Ready even if row-level Generate Message cells have not completed.",
|
|
1289
|
-
"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.",
|
|
1290
|
-
"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.",
|
|
1291
|
-
"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.",
|
|
1292
|
-
"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.",
|
|
1293
|
-
"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."
|
|
1294
|
-
},
|
|
1295
|
-
{
|
|
1296
|
-
"action": "wait_for_lead_filter_rules",
|
|
1297
|
-
"requiredArtifacts": [
|
|
1298
|
-
"lead-filter.md"
|
|
1299
|
-
],
|
|
1300
|
-
"optionalArtifacts": [
|
|
1301
|
-
"rubric.json",
|
|
1302
|
-
"message-validation.md",
|
|
1303
|
-
"message-prep.md",
|
|
1304
|
-
"message-candidate-drafts.md"
|
|
591
|
+
"inputs": [
|
|
592
|
+
"campaignId",
|
|
593
|
+
"campaignBrief",
|
|
594
|
+
"selectedLeadListId",
|
|
595
|
+
"workflowTableId",
|
|
596
|
+
"reviewBatchRowIds/hash",
|
|
597
|
+
"filterChoice"
|
|
1305
598
|
],
|
|
1306
|
-
"
|
|
599
|
+
"stateSource": "CampaignOffer and workflow table rows",
|
|
600
|
+
"debugFilesOptionalOnly": true
|
|
1307
601
|
},
|
|
1308
602
|
{
|
|
1309
603
|
"action": "save_filter_rubrics_to_campaign",
|
|
1310
604
|
"tool": "save_rubrics",
|
|
1311
|
-
"
|
|
1312
|
-
"campaignId",
|
|
1313
|
-
"workflowTableId",
|
|
1314
|
-
"lead-filter.md"
|
|
1315
|
-
],
|
|
1316
|
-
"optionalInput": "rubric.json",
|
|
1317
|
-
"when": "after_imported_campaign_table_sample_and_lead_filter_ready_before_message_review",
|
|
1318
|
-
"fallback": "Stop if campaignId/workflowTableId is missing or save_rubrics fails; do not queue the review-batch cascade without saved rubrics.",
|
|
1319
|
-
"requiredBeforeImport": false,
|
|
605
|
+
"when": "filters_enabled and rubrics are production-shaped",
|
|
1320
606
|
"requiredFields": [
|
|
1321
607
|
"campaignOfferId",
|
|
1322
608
|
"leadScoringRubrics"
|
|
1323
609
|
],
|
|
1324
|
-
"writesCampaignState": "leadScoringRubrics"
|
|
1325
|
-
"requiredBeforeCascade": true
|
|
1326
|
-
},
|
|
1327
|
-
{
|
|
1328
|
-
"action": "advance_watch_to_filter_leads_after_rubrics_saved",
|
|
1329
|
-
"tool": "update_campaign",
|
|
1330
|
-
"requires": [
|
|
1331
|
-
"campaignId",
|
|
1332
|
-
"workflowTableId",
|
|
1333
|
-
"leadScoringRubrics"
|
|
1334
|
-
],
|
|
1335
|
-
"requiredValues": {
|
|
1336
|
-
"currentStep": "apply-icp-rubric",
|
|
1337
|
-
"enableICPFilters": true,
|
|
1338
|
-
"watchNarration.stage": "fit-message"
|
|
1339
|
-
},
|
|
1340
|
-
"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.",
|
|
1341
|
-
"when": "after_save_rubrics_succeeds_before_waiting_for_message_validation_or_queueing_enrichment",
|
|
1342
|
-
"writesCampaignState": "currentStep:apply-icp-rubric"
|
|
1343
|
-
},
|
|
1344
|
-
{
|
|
1345
|
-
"tool": "get_campaign_navigation_state",
|
|
1346
|
-
"purpose": "confirm the watched UI moved to Filter Leads after rubrics saved",
|
|
1347
|
-
"optional": true
|
|
1348
|
-
},
|
|
1349
|
-
{
|
|
1350
|
-
"action": "wait_for_message_draft_recommendation",
|
|
1351
|
-
"requiredOutputs": [
|
|
1352
|
-
"template recommendation",
|
|
1353
|
-
"token fill rules",
|
|
1354
|
-
"rendered sample"
|
|
1355
|
-
],
|
|
1356
|
-
"optionalArtifacts": [
|
|
1357
|
-
"message-validation.md",
|
|
1358
|
-
"message-prep.md",
|
|
1359
|
-
"message-candidate-drafts.md"
|
|
1360
|
-
],
|
|
1361
|
-
"reconciliationRule": "Before entering message-review, verify the recommendation came from the same campaignBrief, selected source state, selectedLeadListId, imported review-batch rows, and saved filters. Saved filters gate the sample rows; debug markdown files are optional only."
|
|
610
|
+
"writesCampaignState": "leadScoringRubrics"
|
|
1362
611
|
}
|
|
1363
612
|
],
|
|
1364
|
-
"
|
|
1365
|
-
|
|
1366
|
-
"
|
|
1367
|
-
"
|
|
1368
|
-
|
|
1369
|
-
"optionalProducesArtifacts": [
|
|
1370
|
-
"rubric.json",
|
|
1371
|
-
"message-prep.md",
|
|
1372
|
-
"message-candidate-drafts.md"
|
|
613
|
+
"requiredCampaignState": [
|
|
614
|
+
"campaignId",
|
|
615
|
+
"campaignBrief",
|
|
616
|
+
"selectedLeadListId",
|
|
617
|
+
"workflowTableId"
|
|
1373
618
|
],
|
|
1374
619
|
"allowedTools": [
|
|
1375
620
|
"get_subskill_prompt",
|
|
1376
621
|
"get_subskill_asset",
|
|
1377
622
|
"get_post_find_leads_scout_registry",
|
|
1378
623
|
"save_rubrics",
|
|
624
|
+
"get_campaign",
|
|
625
|
+
"get_rows_minimal",
|
|
1379
626
|
"update_campaign",
|
|
1380
627
|
"get_campaign_navigation_state",
|
|
1381
|
-
"Task",
|
|
1382
|
-
"spawn_agent",
|
|
1383
628
|
"AskUserQuestion",
|
|
1384
|
-
"request_user_input"
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
"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.",
|
|
1388
|
-
"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.",
|
|
1389
|
-
"Do not let filter-leads create a new message sample. Do not let message-generation fetch new prospects.",
|
|
1390
|
-
"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.",
|
|
1391
|
-
"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.",
|
|
1392
|
-
"Do not attach sequence, start, or queue product Generate Message cells until the approved message set is synced into campaignBrief."
|
|
629
|
+
"request_user_input",
|
|
630
|
+
"Task",
|
|
631
|
+
"spawn_agent"
|
|
1393
632
|
],
|
|
1394
633
|
"doNotAllow": [
|
|
1395
634
|
"create_campaign",
|
|
635
|
+
"list_senders",
|
|
1396
636
|
"import_leads",
|
|
1397
637
|
"confirm_lead_list",
|
|
638
|
+
"queue_cells",
|
|
1398
639
|
"start_campaign",
|
|
1399
640
|
"check_rubric",
|
|
1400
|
-
"generate_messages"
|
|
1401
|
-
"enrich_with_prospeo",
|
|
1402
|
-
"bulk_enrich_with_prospeo"
|
|
641
|
+
"generate_messages"
|
|
1403
642
|
],
|
|
1404
|
-
"watchRequired": true,
|
|
1405
643
|
"waitFor": [
|
|
1406
644
|
"post_lead_workstreams_ready",
|
|
1407
645
|
"revise_leads",
|
|
@@ -1414,150 +652,33 @@
|
|
|
1414
652
|
"revise_rubric": "filter-rubric",
|
|
1415
653
|
"revise_messaging": "message-generation",
|
|
1416
654
|
"confirm_with_user": "message-review"
|
|
1417
|
-
}
|
|
1418
|
-
"interruptOnly": true,
|
|
1419
|
-
"requiredCampaignState": [
|
|
1420
|
-
"campaignId",
|
|
1421
|
-
"campaignBrief",
|
|
1422
|
-
"selectedLeadListId",
|
|
1423
|
-
"workflowTableId"
|
|
1424
|
-
],
|
|
1425
|
-
"debugProducesArtifacts": [
|
|
1426
|
-
"lead-filter.md",
|
|
1427
|
-
"message-validation.md",
|
|
1428
|
-
"rubric.json",
|
|
1429
|
-
"message-prep.md",
|
|
1430
|
-
"message-candidate-drafts.md"
|
|
1431
|
-
]
|
|
1432
|
-
},
|
|
1433
|
-
{
|
|
1434
|
-
"id": "messages-mode-choice",
|
|
1435
|
-
"label": "Messages mode choice",
|
|
1436
|
-
"currentStepValue": null,
|
|
1437
|
-
"normalFlow": false,
|
|
1438
|
-
"onEnter": [
|
|
1439
|
-
{
|
|
1440
|
-
"action": "legacy_resume_only_notice",
|
|
1441
|
-
"rule": "Do not show this question in normal create-campaign runs. Route to message-generation/message-review instead."
|
|
1442
|
-
}
|
|
1443
|
-
],
|
|
1444
|
-
"allowedTools": [
|
|
1445
|
-
"AskUserQuestion",
|
|
1446
|
-
"request_user_input",
|
|
1447
|
-
"update_campaign",
|
|
1448
|
-
"get_campaign_navigation_state"
|
|
1449
|
-
],
|
|
1450
|
-
"doNotAllow": [
|
|
1451
|
-
"create_campaign",
|
|
1452
|
-
"import_leads",
|
|
1453
|
-
"confirm_lead_list",
|
|
1454
|
-
"queue_cells",
|
|
1455
|
-
"start_campaign",
|
|
1456
|
-
"generate_messages",
|
|
1457
|
-
"enrich_with_prospeo",
|
|
1458
|
-
"bulk_enrich_with_prospeo"
|
|
1459
|
-
],
|
|
1460
|
-
"watchRequired": true,
|
|
1461
|
-
"waitFor": [
|
|
1462
|
-
"legacy_resume_only"
|
|
1463
|
-
],
|
|
1464
|
-
"transitions": {
|
|
1465
|
-
"legacy_resume_only": "message-generation"
|
|
1466
|
-
},
|
|
1467
|
-
"interruptOnly": true,
|
|
1468
|
-
"requiredCampaignState": [
|
|
1469
|
-
"campaignId",
|
|
1470
|
-
"campaignBrief",
|
|
1471
|
-
"selectedLeadListId",
|
|
1472
|
-
"workflowTableId"
|
|
1473
|
-
],
|
|
1474
|
-
"resumeOnly": true,
|
|
1475
|
-
"deprecated": true,
|
|
1476
|
-
"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."
|
|
655
|
+
}
|
|
1477
656
|
},
|
|
1478
657
|
{
|
|
1479
658
|
"id": "filter-rubric",
|
|
1480
|
-
"label": "
|
|
659
|
+
"label": "Rubric revision",
|
|
1481
660
|
"onEnter": [
|
|
1482
661
|
{
|
|
1483
|
-
"
|
|
1484
|
-
"
|
|
1485
|
-
|
|
1486
|
-
"
|
|
1487
|
-
|
|
1488
|
-
"lead-sample.json"
|
|
1489
|
-
]
|
|
1490
|
-
},
|
|
1491
|
-
{
|
|
1492
|
-
"action": "write_artifacts",
|
|
1493
|
-
"artifacts": [
|
|
1494
|
-
"lead-filter.md"
|
|
1495
|
-
],
|
|
1496
|
-
"optionalArtifacts": [
|
|
1497
|
-
"rubric.json"
|
|
1498
|
-
]
|
|
1499
|
-
},
|
|
1500
|
-
{
|
|
1501
|
-
"action": "show_lead_filter_summary",
|
|
1502
|
-
"artifact": "lead-filter.md",
|
|
1503
|
-
"renderInlineSections": [
|
|
1504
|
-
"## Lead filter",
|
|
1505
|
-
"Keep",
|
|
1506
|
-
"Exclude",
|
|
1507
|
-
"Why",
|
|
1508
|
-
"Expected impact"
|
|
1509
|
-
],
|
|
1510
|
-
"requiredArtifactLinks": [
|
|
1511
|
-
"lead-filter.md"
|
|
1512
|
-
],
|
|
1513
|
-
"chatRenderRule": "Show a slim rendered-Markdown filter summary before message review, never a fenced code block. Use ## Lead filter plus indexed sections and short bullets for who we keep, who we exclude, sample-backed reason, and expected impact. Keep production rubric fields and rubric.json details in lead-filter.md/rubric.json. Do not show plain filesystem paths unless links cannot be created."
|
|
662
|
+
"tool": "get_subskill_asset",
|
|
663
|
+
"requiredValues": {
|
|
664
|
+
"subskillName": "create-campaign-v2",
|
|
665
|
+
"assetPath": "references/filter-leads.md"
|
|
666
|
+
}
|
|
1514
667
|
},
|
|
1515
668
|
{
|
|
1516
|
-
"action": "save_filter_rubrics_to_campaign",
|
|
1517
669
|
"tool": "save_rubrics",
|
|
1518
|
-
"requires": [
|
|
1519
|
-
"campaignId",
|
|
1520
|
-
"workflowTableId",
|
|
1521
|
-
"lead-filter.md"
|
|
1522
|
-
],
|
|
1523
|
-
"optionalInput": "rubric.json",
|
|
1524
|
-
"when": "after_filter_confirmed_or_auto_continue",
|
|
1525
|
-
"fallback": "Stop if campaignId/workflowTableId is missing or save_rubrics fails; do not queue the review-batch cascade without saved rubrics.",
|
|
1526
|
-
"requiredBeforeImport": false,
|
|
1527
670
|
"requiredFields": [
|
|
1528
671
|
"campaignOfferId",
|
|
1529
672
|
"leadScoringRubrics"
|
|
1530
673
|
],
|
|
1531
|
-
"writesCampaignState": "leadScoringRubrics"
|
|
1532
|
-
"requiredBeforeCascade": true
|
|
1533
|
-
},
|
|
1534
|
-
{
|
|
1535
|
-
"action": "ask_revise_only_if_filter_is_not_confirmed",
|
|
1536
|
-
"autoContinueWhen": {
|
|
1537
|
-
"status": "confirmed",
|
|
1538
|
-
"decisionIn": [
|
|
1539
|
-
"continue",
|
|
1540
|
-
"confirmed"
|
|
1541
|
-
],
|
|
1542
|
-
"expectedUsableLeadsAtLeast": 150,
|
|
1543
|
-
"noHeavyFilteringWarning": true,
|
|
1544
|
-
"noCampaignMissRisk": true
|
|
1545
|
-
}
|
|
674
|
+
"writesCampaignState": "leadScoringRubrics"
|
|
1546
675
|
}
|
|
1547
676
|
],
|
|
1548
|
-
"
|
|
1549
|
-
"
|
|
1550
|
-
"
|
|
1551
|
-
"lead-sample.json"
|
|
1552
|
-
],
|
|
1553
|
-
"producesArtifacts": [
|
|
1554
|
-
"lead-filter.md"
|
|
1555
|
-
],
|
|
1556
|
-
"optionalProducesArtifacts": [
|
|
1557
|
-
"rubric.json"
|
|
677
|
+
"requiredCampaignState": [
|
|
678
|
+
"campaignId",
|
|
679
|
+
"workflowTableId"
|
|
1558
680
|
],
|
|
1559
681
|
"allowedTools": [
|
|
1560
|
-
"get_subskill_prompt",
|
|
1561
682
|
"get_subskill_asset",
|
|
1562
683
|
"save_rubrics",
|
|
1563
684
|
"AskUserQuestion",
|
|
@@ -1565,16 +686,14 @@
|
|
|
1565
686
|
],
|
|
1566
687
|
"doNotAllow": [
|
|
1567
688
|
"create_campaign",
|
|
689
|
+
"list_senders",
|
|
1568
690
|
"import_leads",
|
|
1569
691
|
"confirm_lead_list",
|
|
1570
692
|
"update_campaign",
|
|
1571
693
|
"queue_cells",
|
|
1572
694
|
"start_campaign",
|
|
1573
|
-
"check_rubric"
|
|
1574
|
-
"enrich_with_prospeo",
|
|
1575
|
-
"bulk_enrich_with_prospeo"
|
|
695
|
+
"check_rubric"
|
|
1576
696
|
],
|
|
1577
|
-
"watchRequired": false,
|
|
1578
697
|
"waitFor": [
|
|
1579
698
|
"lead_filter_ready",
|
|
1580
699
|
"revise_leads",
|
|
@@ -1586,65 +705,54 @@
|
|
|
1586
705
|
"revise_leads": "find-leads",
|
|
1587
706
|
"confirm_with_user": "message-generation",
|
|
1588
707
|
"auto_continue": "message-generation"
|
|
1589
|
-
}
|
|
1590
|
-
"interruptOnly": true,
|
|
1591
|
-
"requiredCampaignState": [
|
|
1592
|
-
"campaignId",
|
|
1593
|
-
"workflowTableId"
|
|
1594
|
-
]
|
|
708
|
+
}
|
|
1595
709
|
},
|
|
1596
710
|
{
|
|
1597
711
|
"id": "message-generation",
|
|
1598
712
|
"label": "Message generation",
|
|
1599
713
|
"onEnter": [
|
|
1600
714
|
{
|
|
1601
|
-
"action": "
|
|
1602
|
-
"target": "
|
|
1603
|
-
"
|
|
1604
|
-
"sampleSource": "imported review-batch rows from selectedLeadListId",
|
|
1605
|
-
"toolCallRequiredBeforeArtifacts": [
|
|
715
|
+
"action": "run_or_reconcile_message_draft_builder",
|
|
716
|
+
"target": "post-find-leads-message-scout",
|
|
717
|
+
"toolCallRequiredBeforeDraft": [
|
|
1606
718
|
"get_subskill_prompt({ subskillName: \"generate-messages\", offset, limit }) until hasMore=false",
|
|
1607
719
|
"optional supplemental check: get_subskill_asset({ subskillName: \"create-campaign-v2\", assetPath: \"references/message-review-safety-gate.md\" })"
|
|
1608
720
|
],
|
|
1609
|
-
"
|
|
1610
|
-
"
|
|
1611
|
-
},
|
|
1612
|
-
{
|
|
1613
|
-
"action": "return_template_recommendation",
|
|
1614
|
-
"optionalArtifact": "message-validation.md"
|
|
721
|
+
"stateSource": "campaignBrief, selected source state, selectedLeadListId, workflowTableId, bounded review-batch row ids/hash",
|
|
722
|
+
"outputState": "messageDraftRecommendation"
|
|
1615
723
|
}
|
|
1616
724
|
],
|
|
1617
|
-
"
|
|
1618
|
-
|
|
1619
|
-
"
|
|
725
|
+
"requiredCampaignState": [
|
|
726
|
+
"campaignId",
|
|
727
|
+
"campaignBrief",
|
|
728
|
+
"selectedLeadListId",
|
|
729
|
+
"workflowTableId"
|
|
1620
730
|
],
|
|
1621
731
|
"allowedTools": [
|
|
1622
732
|
"get_subskill_prompt",
|
|
1623
733
|
"get_subskill_asset",
|
|
734
|
+
"get_campaign",
|
|
735
|
+
"get_rows_minimal",
|
|
1624
736
|
"AskUserQuestion",
|
|
1625
737
|
"request_user_input"
|
|
1626
738
|
],
|
|
1627
739
|
"toolRules": [
|
|
1628
|
-
"Before
|
|
740
|
+
"Before message review, load the full get_subskill_prompt({ subskillName: \"generate-messages\" }) prompt and draft from campaignBrief, selected source state, selectedLeadListId, workflowTableId, and imported review-batch rows.",
|
|
1629
741
|
"Do not use brief.md, lead-review.md, or lead-sample.json as required live state; those files are optional debug context only.",
|
|
1630
|
-
"
|
|
1631
|
-
"
|
|
1632
|
-
"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.",
|
|
1633
|
-
"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."
|
|
742
|
+
"The compact messageDraftRecommendation must return templateRecommendation, tokenFillRules, renderedSample, concerns, status, basisToken, outputAt, outputHash, and error or retry detail.",
|
|
743
|
+
"If campaign/source/table/review-batch basis does not match, classify the output stale or blocked."
|
|
1634
744
|
],
|
|
1635
745
|
"doNotAllow": [
|
|
1636
746
|
"create_campaign",
|
|
747
|
+
"list_senders",
|
|
1637
748
|
"save_rubrics",
|
|
1638
749
|
"import_leads",
|
|
1639
750
|
"confirm_lead_list",
|
|
1640
751
|
"update_campaign",
|
|
1641
752
|
"queue_cells",
|
|
1642
753
|
"start_campaign",
|
|
1643
|
-
"generate_messages"
|
|
1644
|
-
"enrich_with_prospeo",
|
|
1645
|
-
"bulk_enrich_with_prospeo"
|
|
754
|
+
"generate_messages"
|
|
1646
755
|
],
|
|
1647
|
-
"watchRequired": false,
|
|
1648
756
|
"waitFor": [
|
|
1649
757
|
"message_validation_ready",
|
|
1650
758
|
"revise_rubric",
|
|
@@ -1658,779 +766,158 @@
|
|
|
1658
766
|
"revise_messaging": "message-generation",
|
|
1659
767
|
"confirm_with_user": "message-review",
|
|
1660
768
|
"auto_continue": "message-review"
|
|
1661
|
-
}
|
|
1662
|
-
"optionalRequiredArtifacts": [
|
|
1663
|
-
"lead-filter.md",
|
|
1664
|
-
"message-prep.md",
|
|
1665
|
-
"message-candidate-drafts.md"
|
|
1666
|
-
],
|
|
1667
|
-
"interruptOnly": true,
|
|
1668
|
-
"requiredCampaignState": [
|
|
1669
|
-
"campaignId",
|
|
1670
|
-
"campaignBrief",
|
|
1671
|
-
"selectedLeadListId",
|
|
1672
|
-
"workflowTableId"
|
|
1673
|
-
]
|
|
769
|
+
}
|
|
1674
770
|
},
|
|
1675
771
|
{
|
|
1676
772
|
"id": "message-review",
|
|
1677
|
-
"label": "Message review
|
|
1678
|
-
"normalFlow": true,
|
|
1679
|
-
"resumeOnly": false,
|
|
773
|
+
"label": "Message review",
|
|
1680
774
|
"onEnter": [
|
|
1681
775
|
{
|
|
1682
|
-
"action": "
|
|
776
|
+
"action": "render_message_review_from_state",
|
|
1683
777
|
"requiredState": [
|
|
1684
778
|
"campaignBrief",
|
|
1685
|
-
"selected source state",
|
|
1686
779
|
"selectedLeadListId",
|
|
1687
780
|
"workflowTableId",
|
|
1688
|
-
"
|
|
1689
|
-
"template recommendation with token fill rules and rendered sample"
|
|
781
|
+
"messageDraftRecommendation"
|
|
1690
782
|
],
|
|
1691
|
-
"
|
|
1692
|
-
"lead-filter.md",
|
|
1693
|
-
"message-validation.md",
|
|
1694
|
-
"message-prep.md",
|
|
1695
|
-
"message-candidate-drafts.md"
|
|
1696
|
-
]
|
|
1697
|
-
},
|
|
1698
|
-
{
|
|
1699
|
-
"action": "write_message_review",
|
|
1700
|
-
"artifact": "message-review.md",
|
|
1701
|
-
"requiredInlineMarker": "Status: message-review",
|
|
1702
|
-
"panels": [
|
|
1703
|
-
"subject",
|
|
1704
|
-
"sample prospect fill",
|
|
1705
|
-
"my take",
|
|
1706
|
-
"concern",
|
|
1707
|
-
"question",
|
|
1708
|
-
"recommendation"
|
|
1709
|
-
],
|
|
1710
|
-
"mustRenderInlineBeforeQuestion": true,
|
|
1711
|
-
"minimumVisibleMessageDetail": "filled_sample_message_only",
|
|
1712
|
-
"requiredArtifactLinks": [
|
|
1713
|
-
"message-review.md"
|
|
1714
|
-
],
|
|
1715
|
-
"artifactLinkTiming": "before_approval_question",
|
|
1716
|
-
"requiredFileLabels": [
|
|
1717
|
-
"Subject:",
|
|
1718
|
-
"Tokenized template:",
|
|
1719
|
-
"Sample prospect fill:",
|
|
1720
|
-
"Token fill basis:",
|
|
1721
|
-
"Rendered examples:",
|
|
1722
|
-
"Good token fill:",
|
|
1723
|
-
"Good omit:",
|
|
1724
|
-
"Bad token fill:",
|
|
1725
|
-
"Why bad:",
|
|
1726
|
-
"Fallback if missing:",
|
|
1727
|
-
"Token notes:",
|
|
1728
|
-
"My take:",
|
|
1729
|
-
"Suggested adjustment:",
|
|
1730
|
-
"Question: approve-message or revise-messaging?",
|
|
1731
|
-
"Recommendation:"
|
|
1732
|
-
],
|
|
1733
|
-
"requiredChatLabels": [
|
|
1734
|
-
"Status: message-review",
|
|
783
|
+
"requiredVisibleLabels": [
|
|
1735
784
|
"Subject:",
|
|
1736
785
|
"Sample prospect fill:",
|
|
1737
786
|
"My take:",
|
|
1738
787
|
"Concern:",
|
|
1739
788
|
"Question: approve-message or revise-messaging?",
|
|
1740
789
|
"Recommendation:"
|
|
1741
|
-
]
|
|
1742
|
-
"chatRenderRule": "Show a slim rendered-Markdown message review, never a fenced code block. Use ## Message review plus indexed sections and short bullets. Show one fully filled sample message with no {{tokens}} before asking for approval. Include subject, sample message, why it should work, one concern or None, recommendation, and Watch link when a campaign shell exists. Keep tokenized template, token fill basis, rendered examples, good/bad token fill examples, validation notes, and message-validation.md details in campaign state or optional debug artifacts. Do not show plain filesystem paths unless the user asks.",
|
|
1743
|
-
"allowedRecommendations": [
|
|
1744
|
-
"approve-message",
|
|
1745
|
-
"revise-messaging"
|
|
1746
|
-
],
|
|
1747
|
-
"judgeAgainst": [
|
|
1748
|
-
"generate-messages rules",
|
|
1749
|
-
"gold-standard-* references",
|
|
1750
|
-
"opener strategy diversity",
|
|
1751
|
-
"raw sendable copy",
|
|
1752
|
-
"concrete enriched-row tokens",
|
|
1753
|
-
"no generic signal tokens",
|
|
1754
|
-
"no bracketed or deferred row instructions",
|
|
1755
|
-
"tokenized template with rendered examples",
|
|
1756
|
-
"tokenized template plus filled sample prospect",
|
|
1757
|
-
"good and bad token-fill examples",
|
|
1758
|
-
"per-token fallback rules for missing row data",
|
|
1759
|
-
"concrete fallback examples, not abstract fallback advice",
|
|
1760
|
-
"complete rendered subject plus body examples",
|
|
1761
|
-
"message-review hard-fail preflight",
|
|
1762
|
-
"A + B + C subject quality",
|
|
1763
|
-
"no generic subject lines",
|
|
1764
|
-
"product job before category nouns",
|
|
1765
|
-
"proof clarity",
|
|
1766
|
-
"CTA usefulness",
|
|
1767
|
-
"length and tightness",
|
|
1768
|
-
"campaign thesis fit"
|
|
1769
|
-
],
|
|
1770
|
-
"userFacing": true
|
|
790
|
+
]
|
|
1771
791
|
},
|
|
1772
792
|
{
|
|
1773
793
|
"action": "ask_message_review_choice",
|
|
794
|
+
"uses": "request_user_input",
|
|
1774
795
|
"choices": [
|
|
1775
796
|
"approve-message",
|
|
1776
797
|
"revise-messaging"
|
|
1777
|
-
]
|
|
1778
|
-
"questionPrerequisiteVisibleLabels": [
|
|
1779
|
-
"Status: message-review",
|
|
1780
|
-
"Subject:",
|
|
1781
|
-
"Tokenized template:",
|
|
1782
|
-
"Sample prospect fill:",
|
|
1783
|
-
"Token fill basis:",
|
|
1784
|
-
"My take:",
|
|
1785
|
-
"Suggested adjustment:",
|
|
1786
|
-
"Recommendation:"
|
|
1787
|
-
],
|
|
1788
|
-
"forbiddenWhenMissingVisibleMessage": true,
|
|
1789
|
-
"doNotOfferShowMessageChoice": true,
|
|
1790
|
-
"stopAfterQuestion": true
|
|
1791
|
-
},
|
|
1792
|
-
{
|
|
1793
|
-
"action": "write_message_review_decision",
|
|
1794
|
-
"artifact": "message-review-decision.md",
|
|
1795
|
-
"allowedChoices": [
|
|
1796
|
-
"approve-message",
|
|
1797
|
-
"revise-messaging"
|
|
1798
|
-
],
|
|
1799
|
-
"authorizesReviewBatchImportWhenApproved": true
|
|
1800
|
-
},
|
|
1801
|
-
{
|
|
1802
|
-
"action": "require_message_review_decision",
|
|
1803
|
-
"artifact": "message-review-decision.md",
|
|
1804
|
-
"requiredValue": "approve-message"
|
|
798
|
+
]
|
|
1805
799
|
},
|
|
1806
800
|
{
|
|
1807
801
|
"action": "sync_approved_message_set_to_campaign_brief",
|
|
1808
802
|
"tool": "update_campaign_brief",
|
|
1809
|
-
"
|
|
1810
|
-
|
|
1811
|
-
"message-review-decision.md",
|
|
1812
|
-
"approved template recommendation",
|
|
1813
|
-
"saved filters when filters are enabled"
|
|
1814
|
-
],
|
|
1815
|
-
"when": "after_message_approved_before_product_messaging",
|
|
1816
|
-
"fields": [
|
|
1817
|
-
"campaignBrief with ## Approved Message Template containing {{...}} tokens, Token Fill Rules, Token Fill Examples"
|
|
1818
|
-
],
|
|
1819
|
-
"requiredBeforeImport": false,
|
|
1820
|
-
"onFailure": "stop_before_import_or_enrichment",
|
|
1821
|
-
"requiredBeforeCascade": true,
|
|
1822
|
-
"writesCampaignState": "campaignBrief.Approved Message Template"
|
|
1823
|
-
},
|
|
1824
|
-
{
|
|
1825
|
-
"action": "advance_watch_after_template_saved_before_cascade",
|
|
1826
|
-
"tool": "update_campaign",
|
|
1827
|
-
"requires": [
|
|
1828
|
-
"campaignId",
|
|
1829
|
-
"campaignBrief.Approved Message Template",
|
|
1830
|
-
"leadScoringRubrics"
|
|
1831
|
-
],
|
|
1832
|
-
"requiredValues": {
|
|
1833
|
-
"currentStep": "apply-icp-rubric",
|
|
1834
|
-
"enableICPFilters": true,
|
|
1835
|
-
"watchNarration.stage": "fit-message",
|
|
1836
|
-
"watchNarration.headline": "Template saved",
|
|
1837
|
-
"watchNarration.workerStatuses.leadFitBuilder": "ready",
|
|
1838
|
-
"watchNarration.workerStatuses.messageDraftBuilder": "ready"
|
|
1839
|
-
},
|
|
1840
|
-
"when": "immediately_after_update_campaign_brief_succeeds_before_get_rows_or_queue_cells",
|
|
1841
|
-
"watchNarrationRule": "Say the approved message template was saved into the campaign brief, the browser is staying on Filter Leads, and Codex is now queueing only the bounded review-batch enrichment/ICP scoring cascade. The Message Draft Builder must be shown as Ready, not In Progress, after this point."
|
|
1842
|
-
},
|
|
1843
|
-
{
|
|
1844
|
-
"tool": "get_rows_minimal",
|
|
1845
|
-
"purpose": "read_bounded_review_batch_cell_ids_after_message_approval",
|
|
1846
|
-
"requiredBeforeCascade": true
|
|
1847
|
-
},
|
|
1848
|
-
{
|
|
1849
|
-
"tool": "queue_cells",
|
|
1850
|
-
"requiredValues": {
|
|
1851
|
-
"tableId": "workflowTableId",
|
|
1852
|
-
"cellSource": "bounded_review_batch_enrichCellIds",
|
|
1853
|
-
"statusFilter": [
|
|
1854
|
-
"pending",
|
|
1855
|
-
"error",
|
|
1856
|
-
"dependency_blocked"
|
|
1857
|
-
]
|
|
1858
|
-
},
|
|
1859
|
-
"purpose": "queue_bounded_review_batch_enrichment_after_approved_template",
|
|
1860
|
-
"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."
|
|
1861
|
-
},
|
|
1862
|
-
{
|
|
1863
|
-
"tool": "wait_for_rubric_results",
|
|
1864
|
-
"requiredValues": {
|
|
1865
|
-
"includeRows": false,
|
|
1866
|
-
"minPassedCount": 2,
|
|
1867
|
-
"targetCount": "bounded review batch count"
|
|
1868
|
-
},
|
|
1869
|
-
"purpose": "wait_for_bounded_filter_run_after_message_approval_before_messages_step",
|
|
1870
|
-
"readVia": "stats_only_tool_result",
|
|
1871
|
-
"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."
|
|
1872
|
-
},
|
|
1873
|
-
{
|
|
1874
|
-
"action": "advance_watch_to_messaging_after_filter_passes",
|
|
1875
|
-
"tool": "update_campaign",
|
|
1876
|
-
"requires": [
|
|
803
|
+
"when": "after approve-message",
|
|
804
|
+
"requiredFields": [
|
|
1877
805
|
"campaignId",
|
|
1878
|
-
"
|
|
1879
|
-
"
|
|
1880
|
-
"
|
|
806
|
+
"approvedMessageTemplate",
|
|
807
|
+
"Token Fill Rules",
|
|
808
|
+
"Token Fill Examples"
|
|
1881
809
|
],
|
|
1882
|
-
"
|
|
1883
|
-
"currentStep": "auto-execute-messaging",
|
|
1884
|
-
"enableICPFilters": true,
|
|
1885
|
-
"watchNarration.stage": "review-ready"
|
|
1886
|
-
},
|
|
1887
|
-
"when": "after_update_campaign_brief_succeeds_and_bounded_filter_run_has_passing_rows",
|
|
1888
|
-
"requiredBeforeGenerateMessageCascade": true,
|
|
1889
|
-
"writesCampaignState": "currentStep:auto-execute-messaging"
|
|
810
|
+
"writesCampaignState": "approvedMessageTemplate"
|
|
1890
811
|
}
|
|
1891
812
|
],
|
|
1892
|
-
"requiredArtifacts": [
|
|
1893
|
-
"brief.md",
|
|
1894
|
-
"lead-review.md",
|
|
1895
|
-
"lead-sample.json",
|
|
1896
|
-
"message-validation.md"
|
|
1897
|
-
],
|
|
1898
|
-
"optionalRequiredArtifacts": [
|
|
1899
|
-
"lead-filter.md"
|
|
1900
|
-
],
|
|
1901
|
-
"producesArtifacts": [
|
|
1902
|
-
"message-review.md",
|
|
1903
|
-
"message-review-decision.md"
|
|
1904
|
-
],
|
|
1905
|
-
"allowedTools": [
|
|
1906
|
-
"AskUserQuestion",
|
|
1907
|
-
"request_user_input",
|
|
1908
|
-
"get_subskill_prompt",
|
|
1909
|
-
"update_campaign_brief",
|
|
1910
|
-
"update_campaign",
|
|
1911
|
-
"get_rows_minimal",
|
|
1912
|
-
"queue_cells",
|
|
1913
|
-
"wait_for_rubric_results"
|
|
1914
|
-
],
|
|
1915
|
-
"doNotAllow": [
|
|
1916
|
-
"create_campaign",
|
|
1917
|
-
"save_rubrics",
|
|
1918
|
-
"import_leads",
|
|
1919
|
-
"confirm_lead_list",
|
|
1920
|
-
"start_campaign",
|
|
1921
|
-
"enrich_with_prospeo",
|
|
1922
|
-
"bulk_enrich_with_prospeo"
|
|
1923
|
-
],
|
|
1924
|
-
"watchRequired": false,
|
|
1925
|
-
"waitFor": [
|
|
1926
|
-
"message_approved",
|
|
1927
|
-
"revise_messaging"
|
|
1928
|
-
],
|
|
1929
|
-
"transitions": {
|
|
1930
|
-
"message_approved": "auto-execute-messaging",
|
|
1931
|
-
"revise_messaging": "message-generation"
|
|
1932
|
-
},
|
|
1933
|
-
"interruptOnly": true,
|
|
1934
813
|
"requiredCampaignState": [
|
|
1935
814
|
"campaignId",
|
|
1936
|
-
"workflowTableId"
|
|
1937
|
-
|
|
1938
|
-
},
|
|
1939
|
-
{
|
|
1940
|
-
"id": "approval-packet",
|
|
1941
|
-
"label": "Approval packet",
|
|
1942
|
-
"normalFlow": false,
|
|
1943
|
-
"resumeOnly": true,
|
|
1944
|
-
"onEnter": [
|
|
1945
|
-
{
|
|
1946
|
-
"action": "read_draft_artifacts",
|
|
1947
|
-
"requiredFiles": [
|
|
1948
|
-
"brief.md",
|
|
1949
|
-
"lead-review.md",
|
|
1950
|
-
"lead-sample.json",
|
|
1951
|
-
"lead-filter.md",
|
|
1952
|
-
"message-validation.md",
|
|
1953
|
-
"message-review.md",
|
|
1954
|
-
"message-review-decision.md"
|
|
1955
|
-
],
|
|
1956
|
-
"optionalFiles": [
|
|
1957
|
-
"rubric.json"
|
|
1958
|
-
]
|
|
1959
|
-
},
|
|
1960
|
-
{
|
|
1961
|
-
"action": "require_message_review_decision",
|
|
1962
|
-
"artifact": "message-review-decision.md",
|
|
1963
|
-
"requiredValue": "approve-message",
|
|
1964
|
-
"doesNotAuthorizeMint": true
|
|
1965
|
-
},
|
|
1966
|
-
{
|
|
1967
|
-
"action": "write_approval_packet",
|
|
1968
|
-
"artifact": "approval-packet.md",
|
|
1969
|
-
"requiredInlineMarker": "Status: approval-packet",
|
|
1970
|
-
"mustRenderInlineBeforeCommitGate": true,
|
|
1971
|
-
"panels": [
|
|
1972
|
-
"campaign direction",
|
|
1973
|
-
"lead source",
|
|
1974
|
-
"filter",
|
|
1975
|
-
"sample message",
|
|
1976
|
-
"what approval creates"
|
|
1977
|
-
],
|
|
1978
|
-
"minimumVisibleDetail": "slim_final_approval_summary",
|
|
1979
|
-
"requiredArtifactLinks": [
|
|
1980
|
-
"approval-packet.md"
|
|
1981
|
-
],
|
|
1982
|
-
"artifactLinkTiming": "before_commit_gate_question",
|
|
1983
|
-
"chatRenderRule": "Show a slim rendered-Markdown final approval packet only, never a fenced code block. Use ## Ready to create campaign plus indexed sections and short bullets. Include target with concrete role/title names, lead source with one key metric, filter summary, one fully filled sample message with no {{tokens}}, what approval creates, and safety note that nothing sends live until the review/greenlight step. Keep tokenized templates, evidence tables, rubrics, and validation details in approval-packet.md. Do not show sequence/settings in final approval; that comes after campaign creation. Do not show plain filesystem paths unless links cannot be created.",
|
|
1984
|
-
"userFacing": true,
|
|
1985
|
-
"doNotUseWords": [
|
|
1986
|
-
"anchor",
|
|
1987
|
-
"validation anchor",
|
|
1988
|
-
"lane"
|
|
1989
|
-
]
|
|
1990
|
-
},
|
|
1991
|
-
{
|
|
1992
|
-
"action": "optional_customer_roleplay",
|
|
1993
|
-
"artifact": "customer-roleplay.md",
|
|
1994
|
-
"advisoryOnly": true,
|
|
1995
|
-
"cannotAuthorizeMint": true
|
|
1996
|
-
}
|
|
1997
|
-
],
|
|
1998
|
-
"requiredArtifacts": [
|
|
1999
|
-
"brief.md",
|
|
2000
|
-
"lead-review.md",
|
|
2001
|
-
"lead-sample.json",
|
|
2002
|
-
"lead-filter.md",
|
|
2003
|
-
"message-validation.md",
|
|
2004
|
-
"message-review.md",
|
|
2005
|
-
"message-review-decision.md"
|
|
2006
|
-
],
|
|
2007
|
-
"producesArtifacts": [
|
|
2008
|
-
"approval-packet.md"
|
|
2009
|
-
],
|
|
2010
|
-
"optionalProducesArtifacts": [
|
|
2011
|
-
"customer-roleplay.md"
|
|
815
|
+
"workflowTableId",
|
|
816
|
+
"messageDraftRecommendation"
|
|
2012
817
|
],
|
|
2013
818
|
"allowedTools": [
|
|
2014
819
|
"AskUserQuestion",
|
|
2015
820
|
"request_user_input",
|
|
2016
|
-
"
|
|
2017
|
-
|
|
2018
|
-
"doNotAllow": [
|
|
2019
|
-
"create_campaign",
|
|
2020
|
-
"save_rubrics",
|
|
2021
|
-
"import_leads",
|
|
2022
|
-
"confirm_lead_list",
|
|
2023
|
-
"update_campaign",
|
|
2024
|
-
"queue_cells",
|
|
2025
|
-
"start_campaign",
|
|
2026
|
-
"enrich_with_prospeo",
|
|
2027
|
-
"bulk_enrich_with_prospeo"
|
|
2028
|
-
],
|
|
2029
|
-
"watchRequired": false,
|
|
2030
|
-
"waitFor": "approval_packet_ready",
|
|
2031
|
-
"transitions": {},
|
|
2032
|
-
"optionalRequiredArtifacts": [
|
|
2033
|
-
"lead-source-intake.json"
|
|
2034
|
-
],
|
|
2035
|
-
"deprecated": true,
|
|
2036
|
-
"deprecatedReason": "Shell-first flow has no final approval gate or mint. Message approval syncs the final template into the existing campaign and transitions directly to Step 13."
|
|
2037
|
-
},
|
|
2038
|
-
{
|
|
2039
|
-
"id": "validate-artifacts",
|
|
2040
|
-
"label": "Validate chained artifacts",
|
|
2041
|
-
"onEnter": [
|
|
2042
|
-
{
|
|
2043
|
-
"action": "read_draft_artifacts",
|
|
2044
|
-
"requiredFiles": [
|
|
2045
|
-
"brief.md",
|
|
2046
|
-
"lead-review.md",
|
|
2047
|
-
"lead-sample.json",
|
|
2048
|
-
"lead-filter.md",
|
|
2049
|
-
"message-validation.md"
|
|
2050
|
-
],
|
|
2051
|
-
"optionalFiles": [
|
|
2052
|
-
"rubric.json"
|
|
2053
|
-
]
|
|
2054
|
-
},
|
|
2055
|
-
{
|
|
2056
|
-
"action": "validate_anchors",
|
|
2057
|
-
"blockOnEmpty": true
|
|
2058
|
-
},
|
|
2059
|
-
{
|
|
2060
|
-
"action": "require_message_review_decision",
|
|
2061
|
-
"artifact": "message-review-decision.md",
|
|
2062
|
-
"requiredValue": "approve-message",
|
|
2063
|
-
"doesNotAuthorizeMint": true
|
|
2064
|
-
}
|
|
2065
|
-
],
|
|
2066
|
-
"allowedTools": [
|
|
2067
|
-
"AskUserQuestion",
|
|
2068
|
-
"request_user_input"
|
|
2069
|
-
],
|
|
2070
|
-
"watchRequired": false,
|
|
2071
|
-
"waitFor": "artifacts_validated",
|
|
2072
|
-
"transitions": {},
|
|
2073
|
-
"optionalRequiredArtifacts": [
|
|
2074
|
-
"lead-source-intake.json"
|
|
2075
|
-
],
|
|
2076
|
-
"deprecated": true,
|
|
2077
|
-
"deprecatedReason": "Shell-first flow has no final approval gate or mint. Message approval syncs the final template into the existing campaign and transitions directly to Step 13.",
|
|
2078
|
-
"resumeOnly": true,
|
|
2079
|
-
"normalFlow": false
|
|
2080
|
-
},
|
|
2081
|
-
{
|
|
2082
|
-
"id": "commit-gate",
|
|
2083
|
-
"label": "Commit gate",
|
|
2084
|
-
"onEnter": [
|
|
2085
|
-
{
|
|
2086
|
-
"action": "require_message_review_decision",
|
|
2087
|
-
"artifact": "message-review-decision.md",
|
|
2088
|
-
"requiredValue": "approve-message",
|
|
2089
|
-
"doesNotAuthorizeMint": true
|
|
2090
|
-
},
|
|
2091
|
-
{
|
|
2092
|
-
"action": "show_approval_packet",
|
|
2093
|
-
"requiredInlineMarker": "Status: approval-packet",
|
|
2094
|
-
"sameTurnAsCommitQuestion": true,
|
|
2095
|
-
"panels": [
|
|
2096
|
-
"campaign direction",
|
|
2097
|
-
"lead source",
|
|
2098
|
-
"filter",
|
|
2099
|
-
"sample message",
|
|
2100
|
-
"what approval creates"
|
|
2101
|
-
],
|
|
2102
|
-
"requiredArtifactLinks": [
|
|
2103
|
-
"approval-packet.md"
|
|
2104
|
-
],
|
|
2105
|
-
"chatRenderRule": "Same slim rendered-Markdown approval packet as approval-packet, never a fenced code block. Use indexed sections and short bullets. Include target with concrete role/title names and one fully filled sample message without tokens. Do not include sequence/settings. Do not repeat tokenized template or long evidence tables in chat.",
|
|
2106
|
-
"artifactLinkTiming": "same_turn_before_commit_question"
|
|
2107
|
-
},
|
|
2108
|
-
{
|
|
2109
|
-
"action": "ask_commit_choice",
|
|
2110
|
-
"choices": [
|
|
2111
|
-
"approve",
|
|
2112
|
-
"revise-brief",
|
|
2113
|
-
"revise-leads",
|
|
2114
|
-
"revise-rubric",
|
|
2115
|
-
"revise-messaging",
|
|
2116
|
-
"abort"
|
|
2117
|
-
]
|
|
2118
|
-
},
|
|
2119
|
-
{
|
|
2120
|
-
"action": "write_commit_gate_decision",
|
|
2121
|
-
"artifact": "commit-gate-decision.md",
|
|
2122
|
-
"allowedChoices": [
|
|
2123
|
-
"approve",
|
|
2124
|
-
"revise-brief",
|
|
2125
|
-
"revise-leads",
|
|
2126
|
-
"revise-rubric",
|
|
2127
|
-
"revise-messaging",
|
|
2128
|
-
"abort"
|
|
2129
|
-
],
|
|
2130
|
-
"onlyApproveAuthorizesMint": true
|
|
2131
|
-
}
|
|
2132
|
-
],
|
|
2133
|
-
"allowedTools": [
|
|
2134
|
-
"AskUserQuestion",
|
|
2135
|
-
"request_user_input"
|
|
2136
|
-
],
|
|
2137
|
-
"watchRequired": false,
|
|
2138
|
-
"waitFor": [
|
|
2139
|
-
"user_approved",
|
|
2140
|
-
"user_revise_brief",
|
|
2141
|
-
"user_revise_leads",
|
|
2142
|
-
"user_revise_rubric",
|
|
2143
|
-
"user_revise_messaging",
|
|
2144
|
-
"user_abort"
|
|
2145
|
-
],
|
|
2146
|
-
"transitions": {},
|
|
2147
|
-
"optionalRequiredArtifacts": [
|
|
2148
|
-
"lead-source-intake.json"
|
|
2149
|
-
],
|
|
2150
|
-
"deprecated": true,
|
|
2151
|
-
"deprecatedReason": "Shell-first flow has no final approval gate or mint. Message approval syncs the final template into the existing campaign and transitions directly to Step 13.",
|
|
2152
|
-
"resumeOnly": true,
|
|
2153
|
-
"normalFlow": false
|
|
2154
|
-
},
|
|
2155
|
-
{
|
|
2156
|
-
"id": "atomic-mint",
|
|
2157
|
-
"label": "Atomic mint",
|
|
2158
|
-
"currentStepValue": "auto-execute-leads",
|
|
2159
|
-
"onEnter": [
|
|
2160
|
-
{
|
|
2161
|
-
"tool": "bootstrap_create_campaign",
|
|
2162
|
-
"requiredValues": {
|
|
2163
|
-
"flowVersion": "v2"
|
|
2164
|
-
}
|
|
2165
|
-
},
|
|
2166
|
-
{
|
|
2167
|
-
"tool": "create_campaign",
|
|
2168
|
-
"mode": "create_new_or_resume_draft_shell",
|
|
2169
|
-
"shellArtifact": "campaign-shell.json",
|
|
2170
|
-
"requiredFields": [
|
|
2171
|
-
"campaignBrief",
|
|
2172
|
-
"currentStep"
|
|
2173
|
-
],
|
|
2174
|
-
"requiredValues": {
|
|
2175
|
-
"currentStep": "auto-execute-leads"
|
|
2176
|
-
},
|
|
2177
|
-
"draftShellBehavior": "If campaign-shell.json exists, call create_campaign with campaignId only to recover watchUrl/resume context, then update_campaign with the final approved brief, provider, and currentStep. If no shell exists, create_campaign mints the campaign with the final approved brief.",
|
|
2178
|
-
"requiredCampaignBriefSections": [
|
|
2179
|
-
"Approved Message Template",
|
|
2180
|
-
"Token Fill Rules",
|
|
2181
|
-
"Token Fill Examples"
|
|
2182
|
-
],
|
|
2183
|
-
"preserveTokenGuidanceFromArtifacts": [
|
|
2184
|
-
"message-review.md",
|
|
2185
|
-
"message-validation.md"
|
|
2186
|
-
],
|
|
2187
|
-
"requiredTokenGuidanceLabels": [
|
|
2188
|
-
"Good token fill:",
|
|
2189
|
-
"Good omit:",
|
|
2190
|
-
"Bad token fill:",
|
|
2191
|
-
"Why bad:",
|
|
2192
|
-
"Fallback if missing:",
|
|
2193
|
-
"Token fill basis:"
|
|
2194
|
-
],
|
|
2195
|
-
"capture": [
|
|
2196
|
-
"campaignId",
|
|
2197
|
-
"watchUrl"
|
|
2198
|
-
],
|
|
2199
|
-
"onMissingWatchUrl": "recoverable_failure_abort_before_rubric_save"
|
|
2200
|
-
},
|
|
2201
|
-
{
|
|
2202
|
-
"tool": "update_campaign",
|
|
2203
|
-
"when": "campaign-shell.json exists",
|
|
2204
|
-
"requiredFields": [
|
|
2205
|
-
"campaignId",
|
|
2206
|
-
"campaignBrief",
|
|
2207
|
-
"currentStep"
|
|
2208
|
-
],
|
|
2209
|
-
"requiredValues": {
|
|
2210
|
-
"currentStep": "auto-execute-leads"
|
|
2211
|
-
},
|
|
2212
|
-
"fields": [
|
|
2213
|
-
"campaignBrief",
|
|
2214
|
-
"leadSourceType",
|
|
2215
|
-
"leadSourceProvider"
|
|
2216
|
-
],
|
|
2217
|
-
"skipWhen": "create_campaign minted a new campaign with the final approved brief and currentStep already set"
|
|
2218
|
-
},
|
|
2219
|
-
{
|
|
2220
|
-
"tool": "save_rubrics",
|
|
2221
|
-
"requiredFields": [
|
|
2222
|
-
"rubric"
|
|
2223
|
-
],
|
|
2224
|
-
"idempotentWhenAlreadySavedToDraftShell": true,
|
|
2225
|
-
"onFailure": "rollback_or_recoverable_stop"
|
|
2226
|
-
},
|
|
2227
|
-
{
|
|
2228
|
-
"action": "flip_brief_status_to_committed"
|
|
2229
|
-
},
|
|
2230
|
-
{
|
|
2231
|
-
"action": "move_draft_dir_to_committed"
|
|
2232
|
-
},
|
|
2233
|
-
{
|
|
2234
|
-
"action": "surface_watch_link",
|
|
2235
|
-
"requires": [
|
|
2236
|
-
"create_campaign_succeeded",
|
|
2237
|
-
"save_rubrics_succeeded"
|
|
2238
|
-
],
|
|
2239
|
-
"reference": "references/watch-link-handoff.md",
|
|
2240
|
-
"requiredVisibleContent": [
|
|
2241
|
-
"Campaign created",
|
|
2242
|
-
"approved brief",
|
|
2243
|
-
"Open this to watch",
|
|
2244
|
-
"Find Leads",
|
|
2245
|
-
"rubric scoring",
|
|
2246
|
-
"messaging populate live",
|
|
2247
|
-
"Watch link:"
|
|
2248
|
-
],
|
|
2249
|
-
"watchUrlSource": "create_campaign.watchUrl"
|
|
2250
|
-
}
|
|
2251
|
-
],
|
|
2252
|
-
"allowedTools": [
|
|
2253
|
-
"bootstrap_create_campaign",
|
|
2254
|
-
"create_campaign",
|
|
821
|
+
"get_subskill_asset",
|
|
822
|
+
"update_campaign_brief",
|
|
2255
823
|
"update_campaign",
|
|
2256
|
-
"
|
|
2257
|
-
"
|
|
2258
|
-
"
|
|
2259
|
-
],
|
|
2260
|
-
"doNotAllow": [
|
|
2261
|
-
"import_leads"
|
|
2262
|
-
],
|
|
2263
|
-
"watchRequired": true,
|
|
2264
|
-
"waitFor": "autonomous_tail_started",
|
|
2265
|
-
"transitions": {},
|
|
2266
|
-
"deprecated": true,
|
|
2267
|
-
"deprecatedReason": "Shell-first flow has no final approval gate or mint. Message approval syncs the final template into the existing campaign and transitions directly to Step 13.",
|
|
2268
|
-
"resumeOnly": true,
|
|
2269
|
-
"normalFlow": false
|
|
2270
|
-
},
|
|
2271
|
-
{
|
|
2272
|
-
"id": "autonomous-tail-handoff",
|
|
2273
|
-
"label": "Handoff to autonomous tail (Plan 85-02)",
|
|
2274
|
-
"onEnter": [
|
|
2275
|
-
{
|
|
2276
|
-
"action": "resume_watch_link"
|
|
2277
|
-
},
|
|
2278
|
-
{
|
|
2279
|
-
"action": "load_auto_execute_config",
|
|
2280
|
-
"source": "core/auto-execute.yaml",
|
|
2281
|
-
"tool": "get_subskill_asset",
|
|
2282
|
-
"requiredValues": {
|
|
2283
|
-
"subskillName": "create-campaign-v2",
|
|
2284
|
-
"assetPath": "core/auto-execute.yaml"
|
|
2285
|
-
},
|
|
2286
|
-
"loadOnce": true
|
|
2287
|
-
},
|
|
2288
|
-
{
|
|
2289
|
-
"action": "handoff_to_plan",
|
|
2290
|
-
"target": "85-02"
|
|
2291
|
-
}
|
|
824
|
+
"get_rows_minimal",
|
|
825
|
+
"queue_cells",
|
|
826
|
+
"wait_for_rubric_results"
|
|
2292
827
|
],
|
|
2293
|
-
"
|
|
2294
|
-
"
|
|
2295
|
-
"
|
|
2296
|
-
"
|
|
828
|
+
"doNotAllow": [
|
|
829
|
+
"create_campaign",
|
|
830
|
+
"list_senders",
|
|
831
|
+
"save_rubrics",
|
|
832
|
+
"import_leads",
|
|
833
|
+
"confirm_lead_list",
|
|
834
|
+
"start_campaign"
|
|
835
|
+
],
|
|
836
|
+
"waitFor": [
|
|
837
|
+
"message_approved",
|
|
838
|
+
"revise_messaging"
|
|
2297
839
|
],
|
|
2298
840
|
"transitions": {
|
|
2299
|
-
"
|
|
841
|
+
"message_approved": "validate-sample",
|
|
842
|
+
"revise_messaging": "message-generation"
|
|
2300
843
|
}
|
|
2301
844
|
},
|
|
2302
845
|
{
|
|
2303
846
|
"id": "validate-sample",
|
|
2304
|
-
"label": "
|
|
847
|
+
"label": "Validate bounded review batch",
|
|
2305
848
|
"currentStepValue": "validate-sample",
|
|
2306
|
-
"normalFlow": false,
|
|
2307
|
-
"resumeOnly": true,
|
|
2308
|
-
"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.",
|
|
2309
849
|
"reference": "references/sample-validation-loop.md",
|
|
2310
|
-
"counter": {
|
|
2311
|
-
"name": "revisionRound",
|
|
2312
|
-
"initialValue": 0,
|
|
2313
|
-
"persistAcrossResume": true,
|
|
2314
|
-
"resetOnResume": false,
|
|
2315
|
-
"capFromConfig": "sample.maxRevisionRounds"
|
|
2316
|
-
},
|
|
2317
850
|
"onEnter": [
|
|
2318
|
-
{
|
|
2319
|
-
"action": "resolve_messages_mode",
|
|
2320
|
-
"branches": {
|
|
2321
|
-
"use-template": "Use the approved template/token rules already synced into CampaignOffer.campaignBrief.",
|
|
2322
|
-
"ai-generated": "Use the explicit AI-generated product path and cancel or ignore any background template draft."
|
|
2323
|
-
},
|
|
2324
|
-
"rule": "AI Generated mode must not read, apply, or be overwritten by the background Message Draft Builder template."
|
|
2325
|
-
},
|
|
2326
|
-
{
|
|
2327
|
-
"action": "watch_mode_orient"
|
|
2328
|
-
},
|
|
2329
851
|
{
|
|
2330
852
|
"tool": "queue_cells",
|
|
2331
|
-
"
|
|
2332
|
-
"
|
|
2333
|
-
|
|
2334
|
-
"
|
|
2335
|
-
"
|
|
853
|
+
"purpose": "queue ICP/enrichment cells for the bounded review batch only",
|
|
854
|
+
"requiredFields": [
|
|
855
|
+
"workflowTableId",
|
|
856
|
+
"reviewBatchRowIds",
|
|
857
|
+
"cellTypes"
|
|
2336
858
|
],
|
|
2337
|
-
"
|
|
859
|
+
"targetCountSource": "reviewBatchRowIds.length"
|
|
2338
860
|
},
|
|
2339
861
|
{
|
|
2340
862
|
"tool": "wait_for_campaign_table_ready",
|
|
2341
|
-
"purpose": "
|
|
863
|
+
"purpose": "wait_for_review_batch_scoring_cells"
|
|
2342
864
|
},
|
|
2343
865
|
{
|
|
2344
866
|
"tool": "get_rows_minimal",
|
|
2345
|
-
"
|
|
2346
|
-
|
|
2347
|
-
|
|
867
|
+
"requiredValues": {
|
|
868
|
+
"includeRows": false
|
|
869
|
+
},
|
|
870
|
+
"purpose": "read compact row status only"
|
|
2348
871
|
},
|
|
2349
872
|
{
|
|
2350
873
|
"tool": "wait_for_rubric_results",
|
|
2351
874
|
"requiredFields": [
|
|
875
|
+
"workflowTableId",
|
|
2352
876
|
"targetCount",
|
|
2353
877
|
"minPassedCount"
|
|
2354
878
|
],
|
|
2355
|
-
"targetCountSource": "stats.totalRows_or_imported_batch_count",
|
|
2356
|
-
"minPassedCountSource": "firstPassingRowForMessageStart (1)",
|
|
2357
879
|
"requiredValues": {
|
|
2358
880
|
"includeRows": false,
|
|
2359
881
|
"minPassedCount": 1
|
|
2360
882
|
},
|
|
2361
|
-
"
|
|
2362
|
-
"readVia": "stats_only_tool_result"
|
|
2363
|
-
"extractFields": [
|
|
2364
|
-
"ready",
|
|
2365
|
-
"partial",
|
|
2366
|
-
"reason",
|
|
2367
|
-
"passRate.completed",
|
|
2368
|
-
"passRate.passed",
|
|
2369
|
-
"passRate.minPassedCount",
|
|
2370
|
-
"stats"
|
|
2371
|
-
],
|
|
2372
|
-
"doNotRetain": "rows_payload",
|
|
2373
|
-
"contextBloatNote": "Pass includeRows=false so the MCP tool returns stats only; 25 rows ≈ 67KB and 100 rows ≈ 268KB when row payloads are retained (see references/sample-validation-loop.md §Known Tool Behaviors #2)."
|
|
883
|
+
"minPassedCountSource": "firstPassingRowForMessageStart",
|
|
884
|
+
"readVia": "stats_only_tool_result"
|
|
2374
885
|
},
|
|
2375
886
|
{
|
|
2376
887
|
"action": "handle_partial_or_timeout_sample",
|
|
2377
|
-
"when": "wait_for_rubric_results.ready_false_or_reason_timeout",
|
|
2378
|
-
"rule": "Do not repeat waits indefinitely. If at least one row has passed, move to Step 15 to observe or queue Generate Message for passing rows even when other sample rows are still processing. If zero rows have passed and active processing is visible, wait once more at most. Otherwise treat returned passRate/stats as a partial sample and stop before Settings with sample_revision_required.",
|
|
2379
888
|
"customerStatus": "sample-needs-revision",
|
|
2380
|
-
"
|
|
2381
|
-
"passRate.completed",
|
|
2382
|
-
"passRate.passed",
|
|
2383
|
-
"passRate.pending",
|
|
2384
|
-
"passRate.percent",
|
|
2385
|
-
"stats.messagesCount"
|
|
2386
|
-
]
|
|
2387
|
-
},
|
|
2388
|
-
{
|
|
2389
|
-
"action": "compute_projected_pass",
|
|
2390
|
-
"formula": "round(passInSample / sampleSize * importLimit)",
|
|
2391
|
-
"floorFromConfig": "sample.minProjectedPass"
|
|
2392
|
-
},
|
|
2393
|
-
{
|
|
2394
|
-
"action": "diagnose_brief_vs_list",
|
|
2395
|
-
"onBrief": "update_campaign_brief_and_rerun",
|
|
2396
|
-
"onList": "escalate",
|
|
2397
|
-
"onUnknown": "escalate"
|
|
2398
|
-
},
|
|
2399
|
-
{
|
|
2400
|
-
"action": "increment_revision_round",
|
|
2401
|
-
"capTripEvent": "escalation_triggered"
|
|
889
|
+
"rule": "Do not repeat waits indefinitely; surface partial status and route to revision."
|
|
2402
890
|
}
|
|
2403
891
|
],
|
|
892
|
+
"requiredCampaignState": [
|
|
893
|
+
"campaignId",
|
|
894
|
+
"workflowTableId",
|
|
895
|
+
"approvedMessageTemplate"
|
|
896
|
+
],
|
|
2404
897
|
"allowedTools": [
|
|
2405
898
|
"get_subskill_asset",
|
|
2406
899
|
"queue_cells",
|
|
2407
900
|
"wait_for_campaign_table_ready",
|
|
2408
901
|
"get_rows_minimal",
|
|
2409
902
|
"wait_for_rubric_results",
|
|
2410
|
-
"update_campaign_brief",
|
|
2411
903
|
"update_campaign",
|
|
2412
904
|
"AskUserQuestion",
|
|
2413
905
|
"request_user_input"
|
|
2414
906
|
],
|
|
2415
907
|
"doNotAllow": [
|
|
2416
908
|
"import_leads",
|
|
909
|
+
"list_senders",
|
|
2417
910
|
"start_campaign",
|
|
2418
911
|
"enrich_with_prospeo",
|
|
2419
912
|
"bulk_enrich_with_prospeo",
|
|
2420
913
|
"check_rubric"
|
|
2421
914
|
],
|
|
2422
915
|
"hardRules": [
|
|
2423
|
-
"list_problem_never_triggers_autonomous_update_campaign_brief",
|
|
2424
|
-
"revision_round_persists_across_resume",
|
|
2425
916
|
"wait_for_rubric_results_never_retain_rows_payload_in_tail_context",
|
|
2426
917
|
"wait_for_rubric_results_targetCount_always_explicit",
|
|
2427
|
-
"first_passing_row_unblocks_generate_message_observation",
|
|
2428
918
|
"timeout_never_repeats_without_customer_handoff",
|
|
2429
|
-
"timeout_or_underfloor_sample_never_advances_to_settings"
|
|
2430
|
-
"review_batch_cascade_waits_for_saved_rubrics_and_approved_template",
|
|
2431
|
-
"generate_message_cells_do_not_run_from_background_template_until_template_token_rules_approved"
|
|
919
|
+
"timeout_or_underfloor_sample_never_advances_to_settings"
|
|
2432
920
|
],
|
|
2433
|
-
"watchRequired": true,
|
|
2434
921
|
"waitFor": [
|
|
2435
922
|
"sample_validated",
|
|
2436
923
|
"sample_revision_required"
|
|
@@ -2441,26 +928,36 @@
|
|
|
2441
928
|
"revise_leads": "find-leads",
|
|
2442
929
|
"revise_rubric": "filter-rubric",
|
|
2443
930
|
"escalation_triggered": "escalation"
|
|
2444
|
-
}
|
|
2445
|
-
"requiredCampaignState": [
|
|
2446
|
-
"campaignId",
|
|
2447
|
-
"workflowTableId",
|
|
2448
|
-
"leadScoringRubrics",
|
|
2449
|
-
"approvedMessageTemplate"
|
|
2450
|
-
]
|
|
931
|
+
}
|
|
2451
932
|
},
|
|
2452
933
|
{
|
|
2453
934
|
"id": "auto-execute-messaging",
|
|
2454
|
-
"label": "
|
|
935
|
+
"label": "Generate review-batch messages",
|
|
2455
936
|
"currentStepValue": "auto-execute-messaging",
|
|
2456
937
|
"references": [
|
|
2457
938
|
"references/parallel-critique-protocol.md",
|
|
2458
939
|
"references/thomas-variant-selection.md",
|
|
2459
|
-
"references/thomas-revision-filters.md"
|
|
940
|
+
"references/thomas-revision-filters.md",
|
|
941
|
+
"references/step-15-re-cascade.md"
|
|
2460
942
|
],
|
|
2461
943
|
"onEnter": [
|
|
2462
944
|
{
|
|
2463
|
-
"
|
|
945
|
+
"tool": "queue_cells",
|
|
946
|
+
"batchSize": 100,
|
|
947
|
+
"when": "any passing row has pending or empty Generate Message cell",
|
|
948
|
+
"cellSource": "pending_generate_message_cells_for_passing_rows using approved_campaign_brief_template"
|
|
949
|
+
},
|
|
950
|
+
{
|
|
951
|
+
"tool": "wait_for_campaign_table_ready",
|
|
952
|
+
"purpose": "wait_for_generate_message_cells_to_complete"
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
"action": "observe_generate_message_results",
|
|
956
|
+
"reference": "references/step-15-re-cascade.md"
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
"action": "enforce_token_contract",
|
|
960
|
+
"modeFromConfig": "messaging.tokenContract"
|
|
2464
961
|
},
|
|
2465
962
|
{
|
|
2466
963
|
"action": "optional_critique_pass",
|
|
@@ -2472,7 +969,6 @@
|
|
|
2472
969
|
"perCriticTimeoutFromConfig": "messaging.critique.perCriticTimeoutSeconds",
|
|
2473
970
|
"totalTimeoutFromConfig": "messaging.critique.totalTimeoutSeconds",
|
|
2474
971
|
"criticsFromConfig": "messaging.critique.critics",
|
|
2475
|
-
"synthesisModelFromConfig": "messaging.critique.synthesis.model",
|
|
2476
972
|
"enforceFinalizerPassFromConfig": "messaging.critique.synthesis.enforceFinalizerPass",
|
|
2477
973
|
"rejectOnFakeProofFromConfig": "messaging.critique.rejectOnFakeProof",
|
|
2478
974
|
"rejectOnUnsupportedTokenFromConfig": "messaging.critique.rejectOnUnsupportedToken",
|
|
@@ -2491,50 +987,13 @@
|
|
|
2491
987
|
"onOpusBudgetTrip": "halt_opus_continue_non_opus",
|
|
2492
988
|
"onOpusTokenContractViolation": "fallback_to_non_opus_rewrite"
|
|
2493
989
|
},
|
|
2494
|
-
{
|
|
2495
|
-
"action": "enforce_token_contract",
|
|
2496
|
-
"modeFromConfig": "messaging.tokenContract"
|
|
2497
|
-
},
|
|
2498
|
-
{
|
|
2499
|
-
"action": "verify_campaign_brief_template_mode",
|
|
2500
|
-
"requiredSection": "Approved Message Template",
|
|
2501
|
-
"requiredPattern": "{{...}}",
|
|
2502
|
-
"onFailure": "runtime_failure_before_messaging",
|
|
2503
|
-
"repairBoundary": "before_import_only",
|
|
2504
|
-
"purpose": "ensure Generate Message uses the approved template instead of full-generation mode"
|
|
2505
|
-
},
|
|
2506
|
-
{
|
|
2507
|
-
"tool": "get_rows_minimal",
|
|
2508
|
-
"purpose": "confirm_passing_rows_have_completed_generate_message_cells"
|
|
2509
|
-
},
|
|
2510
|
-
{
|
|
2511
|
-
"tool": "queue_cells",
|
|
2512
|
-
"cellSource": "pending_generate_message_cells_for_passing_rows_using_approved_campaign_brief_template",
|
|
2513
|
-
"when": "any passing row has pending or empty Generate Message cell",
|
|
2514
|
-
"batchSize": 100
|
|
2515
|
-
},
|
|
2516
|
-
{
|
|
2517
|
-
"tool": "wait_for_campaign_table_ready",
|
|
2518
|
-
"purpose": "wait_for_generate_message_cells_to_complete"
|
|
2519
|
-
},
|
|
2520
|
-
{
|
|
2521
|
-
"action": "observe_generate_message_results",
|
|
2522
|
-
"reference": "references/step-15-re-cascade.md",
|
|
2523
|
-
"trigger": "rows_flipped_pending_to_passed_after_first_generate_messages",
|
|
2524
|
-
"note": "Generate Message is produced by the workflow-table cascade. Do not call direct generate_messages in the autonomous tail."
|
|
2525
|
-
},
|
|
2526
990
|
{
|
|
2527
991
|
"tool": "update_campaign",
|
|
2528
|
-
"requiredFields": [
|
|
2529
|
-
"campaignId",
|
|
2530
|
-
"currentStep",
|
|
2531
|
-
"watchNarration"
|
|
2532
|
-
],
|
|
2533
992
|
"requiredValues": {
|
|
2534
993
|
"currentStep": "awaiting-user-greenlight",
|
|
2535
994
|
"watchNarration.stage": "review-ready"
|
|
2536
995
|
},
|
|
2537
|
-
"watchNarrationRule": "Say
|
|
996
|
+
"watchNarrationRule": "Say what just happened, that review-batch messages are ready, and that the next action is Settings/sender review."
|
|
2538
997
|
}
|
|
2539
998
|
],
|
|
2540
999
|
"allowedTools": [
|
|
@@ -2542,13 +1001,13 @@
|
|
|
2542
1001
|
"get_rows_minimal",
|
|
2543
1002
|
"queue_cells",
|
|
2544
1003
|
"wait_for_campaign_table_ready",
|
|
2545
|
-
"update_campaign_brief",
|
|
2546
1004
|
"update_campaign",
|
|
2547
1005
|
"AskUserQuestion",
|
|
2548
1006
|
"request_user_input"
|
|
2549
1007
|
],
|
|
2550
1008
|
"doNotAllow": [
|
|
2551
1009
|
"import_leads",
|
|
1010
|
+
"list_senders",
|
|
2552
1011
|
"start_campaign",
|
|
2553
1012
|
"generate_messages"
|
|
2554
1013
|
],
|
|
@@ -2558,12 +1017,8 @@
|
|
|
2558
1017
|
"critics_fixed_at_targeting_copy_voice",
|
|
2559
1018
|
"synthesis_enforces_phase_84_token_contract",
|
|
2560
1019
|
"opus_reserved_for_highest_value_subset",
|
|
2561
|
-
"proposed_token_never_persisted_in_rewrite"
|
|
2562
|
-
"generate_messages_must_re_cascade_on_newly_passed_rows",
|
|
2563
|
-
"campaign_brief_must_contain_approved_message_template_tokens_before_generate_message_cascade",
|
|
2564
|
-
"generate_message_cells_do_not_run_from_background_template_until_template_token_rules_approved"
|
|
1020
|
+
"proposed_token_never_persisted_in_rewrite"
|
|
2565
1021
|
],
|
|
2566
|
-
"watchRequired": true,
|
|
2567
1022
|
"waitFor": [
|
|
2568
1023
|
"review_batch_ready",
|
|
2569
1024
|
"sample_revision_required"
|
|
@@ -2575,7 +1030,7 @@
|
|
|
2575
1030
|
},
|
|
2576
1031
|
{
|
|
2577
1032
|
"id": "awaiting-user-greenlight",
|
|
2578
|
-
"label": "
|
|
1033
|
+
"label": "Settings, sender, sequence, and greenlight",
|
|
2579
1034
|
"currentStepValue": "awaiting-user-greenlight",
|
|
2580
1035
|
"reference": "references/final-handoff-contract.md",
|
|
2581
1036
|
"onEnter": [
|
|
@@ -2585,7 +1040,7 @@
|
|
|
2585
1040
|
},
|
|
2586
1041
|
{
|
|
2587
1042
|
"tool": "list_senders",
|
|
2588
|
-
"purpose": "surface available connected senders
|
|
1043
|
+
"purpose": "surface available connected senders only at Settings"
|
|
2589
1044
|
},
|
|
2590
1045
|
{
|
|
2591
1046
|
"tool": "update_campaign",
|
|
@@ -2594,24 +1049,16 @@
|
|
|
2594
1049
|
"watchNarration.stage": "review-ready"
|
|
2595
1050
|
},
|
|
2596
1051
|
"purpose": "park the watched UI on Settings before sender selection",
|
|
2597
|
-
"watchNarrationRule": "Say message review is complete and the browser is now on Settings so the user can connect or choose a sender. Include
|
|
2598
|
-
},
|
|
2599
|
-
{
|
|
2600
|
-
"tool": "get_campaign_navigation_state",
|
|
2601
|
-
"purpose": "confirm the watched UI is oriented to Settings before sender selection",
|
|
2602
|
-
"optional": true
|
|
1052
|
+
"watchNarrationRule": "Say message review is complete and the browser is now on Settings so the user can connect or choose a sender. Include that no launch happens from Settings."
|
|
2603
1053
|
},
|
|
2604
1054
|
{
|
|
2605
1055
|
"action": "surface_sender_and_slack_handoff",
|
|
2606
|
-
"settingsUrlPattern": "/campaign-builder/{campaignId}/settings?mode={claude|codex}",
|
|
2607
1056
|
"requiredVisibleContent": [
|
|
2608
1057
|
"connect or select a LinkedIn sender",
|
|
2609
1058
|
"Slack reply review",
|
|
2610
|
-
"
|
|
1059
|
+
"recommended sequence",
|
|
2611
1060
|
"nothing starts until the user confirms launch"
|
|
2612
|
-
]
|
|
2613
|
-
"onNoAvailableSender": "surface settings link and wait for sender_connection_required",
|
|
2614
|
-
"onAvailableSender": "ask the user which connected sender to attach"
|
|
1061
|
+
]
|
|
2615
1062
|
},
|
|
2616
1063
|
{
|
|
2617
1064
|
"action": "ask_sender_selection",
|
|
@@ -2621,8 +1068,7 @@
|
|
|
2621
1068
|
"Use this connected sender",
|
|
2622
1069
|
"Connect a different sender in Settings",
|
|
2623
1070
|
"Pause here"
|
|
2624
|
-
]
|
|
2625
|
-
"uatSafety": "Only auto-select a mock/safe sender when an explicit UAT safe-mode sender is active; never select a real sender in UAT."
|
|
1071
|
+
]
|
|
2626
1072
|
},
|
|
2627
1073
|
{
|
|
2628
1074
|
"action": "attach_selected_sender",
|
|
@@ -2635,59 +1081,17 @@
|
|
|
2635
1081
|
"currentStep": "sequence",
|
|
2636
1082
|
"watchNarration.stage": "review-ready"
|
|
2637
1083
|
},
|
|
2638
|
-
"watchNarrationRule": "Say the sender was attached and the browser is moving to Sequence.
|
|
2639
|
-
},
|
|
2640
|
-
{
|
|
2641
|
-
"tool": "get_campaign_navigation_state",
|
|
2642
|
-
"purpose": "confirm the watched UI moved to Sequence after sender attach",
|
|
2643
|
-
"optional": true
|
|
1084
|
+
"watchNarrationRule": "Say the sender was attached and the browser is moving to Sequence."
|
|
2644
1085
|
},
|
|
2645
1086
|
{
|
|
2646
1087
|
"tool": "attach_recommended_sequence",
|
|
2647
1088
|
"when": "after senderIds are attached",
|
|
2648
1089
|
"requiredValues": {
|
|
2649
1090
|
"campaignId": "{campaignId}",
|
|
2650
|
-
"currentStep": "send"
|
|
2651
|
-
},
|
|
2652
|
-
"purpose": "bind the tier-aware recommended sequence before the launch decision",
|
|
2653
|
-
"watchNarrationRule": "The sequence tool may persist currentStep. If it does, the same visible beat must still explain that the recommended sequence is attached and Send is next; otherwise follow with update_campaign and watchNarration before asking for launch greenlight."
|
|
2654
|
-
},
|
|
2655
|
-
{
|
|
2656
|
-
"tool": "update_campaign",
|
|
2657
|
-
"when": "after recommended sequence attach; required if sequence attach did not persist watchNarration with currentStep",
|
|
2658
|
-
"requiredValues": {
|
|
2659
1091
|
"currentStep": "send",
|
|
2660
1092
|
"watchNarration.stage": "review-ready"
|
|
2661
1093
|
},
|
|
2662
|
-
"
|
|
2663
|
-
"watchNarrationRule": "Say the sender and sequence are ready and the browser is now on Send. The next action is the final launch greenlight; do not imply anything has sent yet."
|
|
2664
|
-
},
|
|
2665
|
-
{
|
|
2666
|
-
"tool": "get_campaign_navigation_state",
|
|
2667
|
-
"purpose": "confirm the watched UI is on Send before final launch greenlight",
|
|
2668
|
-
"optional": true
|
|
2669
|
-
},
|
|
2670
|
-
{
|
|
2671
|
-
"action": "surface_watch_link",
|
|
2672
|
-
"requires": [
|
|
2673
|
-
"campaign_shell_created",
|
|
2674
|
-
"rubrics_saved_to_campaign",
|
|
2675
|
-
"message_set_synced_to_brief"
|
|
2676
|
-
]
|
|
2677
|
-
},
|
|
2678
|
-
{
|
|
2679
|
-
"action": "surface_source_materialization_summary",
|
|
2680
|
-
"manifest": "lead-source-intake.json",
|
|
2681
|
-
"requiredFields": [
|
|
2682
|
-
"sourceType",
|
|
2683
|
-
"sourceRowCount",
|
|
2684
|
-
"reviewBatchImportedCount"
|
|
2685
|
-
],
|
|
2686
|
-
"note": "Say only the first review batch was enriched/messaged before greenlight."
|
|
2687
|
-
},
|
|
2688
|
-
{
|
|
2689
|
-
"action": "surface_orientation",
|
|
2690
|
-
"fromConfig": "handoff.orientation"
|
|
1094
|
+
"watchNarrationRule": "The sequence tool owns the visible beat: say the recommended sequence is attached, the browser is now on Send, and the next action is final launch greenlight. Do not follow with a separate step-only update_campaign fixup."
|
|
2691
1095
|
},
|
|
2692
1096
|
{
|
|
2693
1097
|
"action": "ask_final_launch_greenlight",
|
|
@@ -2698,13 +1102,10 @@
|
|
|
2698
1102
|
"Review campaign first",
|
|
2699
1103
|
"Pause here"
|
|
2700
1104
|
],
|
|
2701
|
-
"onUserStart": "claude-greenlight"
|
|
2702
|
-
"onReviewFirst": "awaiting-user-greenlight",
|
|
2703
|
-
"onPause": "awaiting-user-greenlight"
|
|
1105
|
+
"onUserStart": "claude-greenlight"
|
|
2704
1106
|
}
|
|
2705
1107
|
],
|
|
2706
1108
|
"allowedTools": [
|
|
2707
|
-
"get_subskill_asset",
|
|
2708
1109
|
"get_campaign",
|
|
2709
1110
|
"get_campaign_navigation_state",
|
|
2710
1111
|
"list_senders",
|
|
@@ -2734,38 +1135,17 @@
|
|
|
2734
1135
|
"ready_to_launch": "awaiting-user-greenlight",
|
|
2735
1136
|
"user_greenlight": "claude-greenlight",
|
|
2736
1137
|
"ui_start_detected": "running"
|
|
2737
|
-
}
|
|
2738
|
-
"optionalRequiredArtifacts": [
|
|
2739
|
-
"lead-source-intake.json"
|
|
2740
|
-
]
|
|
1138
|
+
}
|
|
2741
1139
|
},
|
|
2742
1140
|
{
|
|
2743
1141
|
"id": "claude-greenlight",
|
|
2744
|
-
"label": "
|
|
1142
|
+
"label": "Explicit launch",
|
|
2745
1143
|
"reference": "references/final-handoff-contract.md",
|
|
2746
1144
|
"onEnter": [
|
|
2747
1145
|
{
|
|
2748
1146
|
"tool": "get_campaign",
|
|
2749
1147
|
"purpose": "detect_already_running"
|
|
2750
1148
|
},
|
|
2751
|
-
{
|
|
2752
|
-
"action": "short_circuit_if_already_running",
|
|
2753
|
-
"onAlreadyRunning": "running"
|
|
2754
|
-
},
|
|
2755
|
-
{
|
|
2756
|
-
"action": "validate_workspace_sender_invariant"
|
|
2757
|
-
},
|
|
2758
|
-
{
|
|
2759
|
-
"tool": "attach_recommended_sequence",
|
|
2760
|
-
"when": "sequence missing and campaign has attached sender",
|
|
2761
|
-
"purpose": "greenlight repair before approving/sending"
|
|
2762
|
-
},
|
|
2763
|
-
{
|
|
2764
|
-
"action": "bulk_approve_messages",
|
|
2765
|
-
"endpoint": "POST /api/v3/workflow-tables/cells/approve-batch",
|
|
2766
|
-
"reuseExisting": true,
|
|
2767
|
-
"doNotInventNewEndpoint": true
|
|
2768
|
-
},
|
|
2769
1149
|
{
|
|
2770
1150
|
"action": "verify_sequence_and_current_step_before_start",
|
|
2771
1151
|
"requiredState": [
|
|
@@ -2773,8 +1153,7 @@
|
|
|
2773
1153
|
"senderIds",
|
|
2774
1154
|
"sequenceTemplate",
|
|
2775
1155
|
"currentStep in awaiting-user-greenlight|claude-greenlight|send"
|
|
2776
|
-
]
|
|
2777
|
-
"onFailure": "surface recoverable pre-start refusal and remain in awaiting-user-greenlight"
|
|
1156
|
+
]
|
|
2778
1157
|
},
|
|
2779
1158
|
{
|
|
2780
1159
|
"tool": "start_campaign",
|
|
@@ -2783,14 +1162,6 @@
|
|
|
2783
1162
|
],
|
|
2784
1163
|
"persistsCurrentStep": "running",
|
|
2785
1164
|
"watchNarrationRule": "After start_campaign succeeds, the running state must say the final greenlight was accepted, the campaign is now live/running, and the user can watch progress from the campaign."
|
|
2786
|
-
},
|
|
2787
|
-
{
|
|
2788
|
-
"action": "surface_watch_link",
|
|
2789
|
-
"requires": [
|
|
2790
|
-
"campaign_shell_created",
|
|
2791
|
-
"sequence_attached",
|
|
2792
|
-
"start_campaign_succeeded"
|
|
2793
|
-
]
|
|
2794
1165
|
}
|
|
2795
1166
|
],
|
|
2796
1167
|
"allowedTools": [
|
|
@@ -2830,29 +1201,8 @@
|
|
|
2830
1201
|
},
|
|
2831
1202
|
{
|
|
2832
1203
|
"id": "escalation",
|
|
2833
|
-
"label": "Escalation
|
|
1204
|
+
"label": "Escalation",
|
|
2834
1205
|
"reference": "references/escalation-ladder.md",
|
|
2835
|
-
"onEnter": [
|
|
2836
|
-
{
|
|
2837
|
-
"action": "preserve_current_step"
|
|
2838
|
-
},
|
|
2839
|
-
{
|
|
2840
|
-
"action": "write_diagnostic_and_history",
|
|
2841
|
-
"target": "workflow_table_notes_or_skill_artifact"
|
|
2842
|
-
},
|
|
2843
|
-
{
|
|
2844
|
-
"action": "resume_watch_link"
|
|
2845
|
-
},
|
|
2846
|
-
{
|
|
2847
|
-
"action": "ask_user_options",
|
|
2848
|
-
"choices": [
|
|
2849
|
-
"revise-brief",
|
|
2850
|
-
"revise-leads",
|
|
2851
|
-
"abort",
|
|
2852
|
-
"resume-from-step"
|
|
2853
|
-
]
|
|
2854
|
-
}
|
|
2855
|
-
],
|
|
2856
1206
|
"allowedTools": [
|
|
2857
1207
|
"AskUserQuestion",
|
|
2858
1208
|
"request_user_input"
|
|
@@ -2861,186 +1211,22 @@
|
|
|
2861
1211
|
"start_campaign",
|
|
2862
1212
|
"import_leads"
|
|
2863
1213
|
],
|
|
2864
|
-
"
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
"action": "route_back",
|
|
2872
|
-
"target": "phase-83-or-84"
|
|
2873
|
-
},
|
|
2874
|
-
{
|
|
2875
|
-
"action": "reset_draft_artifacts",
|
|
2876
|
-
"preserve": [],
|
|
2877
|
-
"delete": [
|
|
2878
|
-
"lead-review.md",
|
|
2879
|
-
"lead-sample.json",
|
|
2880
|
-
"lead-filter.md",
|
|
2881
|
-
"message-validation.md",
|
|
2882
|
-
"rubric.json"
|
|
2883
|
-
]
|
|
2884
|
-
}
|
|
2885
|
-
],
|
|
2886
|
-
"allowedTools": [
|
|
2887
|
-
"AskUserQuestion",
|
|
2888
|
-
"request_user_input"
|
|
2889
|
-
],
|
|
2890
|
-
"doNotAllow": [
|
|
2891
|
-
"create_campaign",
|
|
2892
|
-
"save_rubrics",
|
|
2893
|
-
"import_leads"
|
|
2894
|
-
],
|
|
2895
|
-
"terminal": true
|
|
2896
|
-
},
|
|
2897
|
-
{
|
|
2898
|
-
"id": "revise-leads",
|
|
2899
|
-
"label": "Revise leads",
|
|
2900
|
-
"onEnter": [
|
|
2901
|
-
{
|
|
2902
|
-
"action": "route_back",
|
|
2903
|
-
"target": "phase-84-find-leads"
|
|
2904
|
-
},
|
|
2905
|
-
{
|
|
2906
|
-
"action": "reset_draft_artifacts",
|
|
2907
|
-
"preserve": [
|
|
2908
|
-
"brief.md"
|
|
2909
|
-
],
|
|
2910
|
-
"delete": [
|
|
2911
|
-
"lead-review.md",
|
|
2912
|
-
"lead-sample.json",
|
|
2913
|
-
"lead-filter.md",
|
|
2914
|
-
"message-validation.md",
|
|
2915
|
-
"rubric.json"
|
|
2916
|
-
]
|
|
2917
|
-
}
|
|
2918
|
-
],
|
|
2919
|
-
"allowedTools": [
|
|
2920
|
-
"AskUserQuestion",
|
|
2921
|
-
"request_user_input"
|
|
2922
|
-
],
|
|
2923
|
-
"doNotAllow": [
|
|
2924
|
-
"create_campaign",
|
|
2925
|
-
"save_rubrics",
|
|
2926
|
-
"import_leads"
|
|
2927
|
-
],
|
|
2928
|
-
"terminal": true
|
|
2929
|
-
},
|
|
2930
|
-
{
|
|
2931
|
-
"id": "revise-rubric",
|
|
2932
|
-
"label": "Revise rubric",
|
|
2933
|
-
"onEnter": [
|
|
2934
|
-
{
|
|
2935
|
-
"action": "route_back",
|
|
2936
|
-
"target": "phase-84-filter-leads"
|
|
2937
|
-
},
|
|
2938
|
-
{
|
|
2939
|
-
"action": "reset_draft_artifacts",
|
|
2940
|
-
"preserve": [
|
|
2941
|
-
"brief.md",
|
|
2942
|
-
"lead-review.md",
|
|
2943
|
-
"lead-sample.json"
|
|
2944
|
-
],
|
|
2945
|
-
"delete": [
|
|
2946
|
-
"lead-filter.md",
|
|
2947
|
-
"message-validation.md",
|
|
2948
|
-
"rubric.json"
|
|
2949
|
-
]
|
|
2950
|
-
}
|
|
2951
|
-
],
|
|
2952
|
-
"allowedTools": [
|
|
2953
|
-
"AskUserQuestion",
|
|
2954
|
-
"request_user_input"
|
|
2955
|
-
],
|
|
2956
|
-
"doNotAllow": [
|
|
2957
|
-
"create_campaign",
|
|
2958
|
-
"save_rubrics",
|
|
2959
|
-
"import_leads"
|
|
2960
|
-
],
|
|
2961
|
-
"terminal": true
|
|
2962
|
-
},
|
|
2963
|
-
{
|
|
2964
|
-
"id": "revise-messaging",
|
|
2965
|
-
"label": "Revise messaging",
|
|
2966
|
-
"onEnter": [
|
|
2967
|
-
{
|
|
2968
|
-
"action": "route_back",
|
|
2969
|
-
"target": "phase-84-generate-message"
|
|
2970
|
-
},
|
|
2971
|
-
{
|
|
2972
|
-
"action": "reset_draft_artifacts",
|
|
2973
|
-
"preserve": [
|
|
2974
|
-
"brief.md",
|
|
2975
|
-
"lead-review.md",
|
|
2976
|
-
"lead-sample.json",
|
|
2977
|
-
"lead-filter.md"
|
|
2978
|
-
],
|
|
2979
|
-
"delete": [
|
|
2980
|
-
"message-validation.md"
|
|
2981
|
-
]
|
|
2982
|
-
}
|
|
2983
|
-
],
|
|
2984
|
-
"allowedTools": [
|
|
2985
|
-
"AskUserQuestion",
|
|
2986
|
-
"request_user_input"
|
|
2987
|
-
],
|
|
2988
|
-
"doNotAllow": [
|
|
2989
|
-
"create_campaign",
|
|
2990
|
-
"save_rubrics",
|
|
2991
|
-
"import_leads"
|
|
2992
|
-
],
|
|
2993
|
-
"terminal": true
|
|
1214
|
+
"transitions": {
|
|
1215
|
+
"revise_brief": "brief-interview",
|
|
1216
|
+
"revise_leads": "find-leads",
|
|
1217
|
+
"revise_rubric": "filter-rubric",
|
|
1218
|
+
"revise_messaging": "message-generation",
|
|
1219
|
+
"abort": "abort"
|
|
1220
|
+
}
|
|
2994
1221
|
},
|
|
2995
1222
|
{
|
|
2996
1223
|
"id": "abort",
|
|
2997
1224
|
"label": "Abort",
|
|
2998
|
-
"onEnter": [
|
|
2999
|
-
{
|
|
3000
|
-
"action": "move_draft_dir",
|
|
3001
|
-
"target": ".aborted/"
|
|
3002
|
-
}
|
|
3003
|
-
],
|
|
3004
1225
|
"allowedTools": [
|
|
3005
1226
|
"AskUserQuestion",
|
|
3006
1227
|
"request_user_input"
|
|
3007
1228
|
],
|
|
3008
|
-
"doNotAllow": [
|
|
3009
|
-
"create_campaign",
|
|
3010
|
-
"save_rubrics",
|
|
3011
|
-
"import_leads"
|
|
3012
|
-
],
|
|
3013
1229
|
"terminal": true
|
|
3014
1230
|
}
|
|
3015
|
-
],
|
|
3016
|
-
"canonicalStateFields": [
|
|
3017
|
-
"campaignId",
|
|
3018
|
-
"watchUrl",
|
|
3019
|
-
"campaignBrief",
|
|
3020
|
-
"currentStep",
|
|
3021
|
-
"providerSearchAssociation",
|
|
3022
|
-
"selectedLeadListId",
|
|
3023
|
-
"workflowTableId",
|
|
3024
|
-
"leadScoringRubrics",
|
|
3025
|
-
"approvedMessageTemplate",
|
|
3026
|
-
"senderIds",
|
|
3027
|
-
"sequenceTemplate",
|
|
3028
|
-
"runningState"
|
|
3029
|
-
],
|
|
3030
|
-
"debugArtifacts": [
|
|
3031
|
-
"brief.md",
|
|
3032
|
-
"campaign-shell.json",
|
|
3033
|
-
"lead-source-intake.json",
|
|
3034
|
-
"lead-review.md",
|
|
3035
|
-
"lead-sample.json",
|
|
3036
|
-
"lead-filter.md",
|
|
3037
|
-
"rubric.json",
|
|
3038
|
-
"message-validation.md",
|
|
3039
|
-
"message-prep.md",
|
|
3040
|
-
"message-candidate-drafts.md",
|
|
3041
|
-
"message-review.md",
|
|
3042
|
-
"message-review-decision.md",
|
|
3043
|
-
"approval-packet.md",
|
|
3044
|
-
"commit-gate-decision.md"
|
|
3045
1231
|
]
|
|
3046
1232
|
}
|