@sellable/mcp 0.1.136 → 0.1.138
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 +21 -0
- package/agents/registry.json +9 -16
- package/agents/source-scout-linkedin-engagement.md +2 -2
- package/dist/engage-memory.d.ts +13 -0
- package/dist/engage-memory.js +129 -34
- package/dist/identity-compiler.d.ts +119 -0
- package/dist/identity-compiler.js +344 -0
- package/dist/identity-memory.d.ts +49 -0
- package/dist/identity-memory.js +89 -0
- package/dist/index-dev.js +0 -0
- package/dist/index.js +0 -0
- package/dist/tools/bootstrap.js +1 -1
- package/dist/tools/engage-memory.js +2 -2
- package/dist/tools/navigation.js +3 -0
- package/dist/tools/prompts.d.ts +1 -4
- package/dist/tools/prompts.js +3 -3
- package/package.json +1 -1
- package/skills/craft-message/SKILL.md +13 -4
- package/skills/create-campaign/references/brief-template.md +2 -1
- package/skills/create-campaign-v2/SKILL.md +150 -1342
- package/skills/create-campaign-v2/core/flow.v2.json +471 -1970
- package/skills/create-post/SKILL.md +54 -9
- package/skills/engage/SKILL.md +37 -15
- package/skills/engage/core/README.md +18 -12
- package/skills/generate-messages/SKILL.md +15 -5
- package/skills/interview/SKILL.md +183 -89
- package/skills/interview/references/anti-ai-audit.md +101 -0
- package/skills/interview/references/compiler-schema.md +94 -0
- package/skills/interview/references/legacy-linkedin-interview.md +118 -0
- package/skills/interview/references/question-bank.md +123 -0
- package/skills/interview/references/reference-curation.md +68 -0
- package/skills/interview/references/voice-capture-method.md +62 -0
|
@@ -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,43 +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": ["AskUserQuestion", "request_user_input"],
|
|
172
|
-
"questionType": "single-choice only; plain chat only for free-text custom detail",
|
|
173
|
-
"multiSelect": false,
|
|
174
|
-
"maxOptions": 4,
|
|
175
|
-
"requiredOption": "Other / custom",
|
|
176
|
-
"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."
|
|
177
142
|
},
|
|
178
143
|
{
|
|
179
144
|
"action": "run_campaign_identity_research_before_strategy_packet",
|
|
180
145
|
"target": "research-sender",
|
|
181
|
-
"
|
|
146
|
+
"requiredCompletion": "complete_sender_research",
|
|
182
147
|
"allowedTools": [
|
|
183
148
|
"get_subskill_prompt",
|
|
184
149
|
"fetch_linkedin_profile",
|
|
@@ -187,108 +152,19 @@
|
|
|
187
152
|
"fetch_company_posts",
|
|
188
153
|
"WebFetch",
|
|
189
154
|
"WebSearch",
|
|
190
|
-
"ToolSearch",
|
|
191
155
|
"complete_sender_research"
|
|
192
|
-
],
|
|
193
|
-
"requiredCompletion": "complete_sender_research",
|
|
194
|
-
"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.",
|
|
195
|
-
"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."
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
"action": "skip_strategy_packet_when_initial_context_is_sufficient",
|
|
199
|
-
"when": "after_identity_lookup_before_founder_strategy_source_packet",
|
|
200
|
-
"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",
|
|
201
|
-
"requiredCoveredFields": [
|
|
202
|
-
"identity_or_client_context",
|
|
203
|
-
"target_prospects",
|
|
204
|
-
"offer_or_cta",
|
|
205
|
-
"proof_guidance",
|
|
206
|
-
"lead_source_preference_or_find_people_permission"
|
|
207
|
-
],
|
|
208
|
-
"effect": "mark founder_strategy_source_packet_answered and proceed to render_post_intake_progress_preamble without asking setup questions again",
|
|
209
|
-
"askOnlyWhen": [
|
|
210
|
-
"a required covered field is missing",
|
|
211
|
-
"the supplied inputs conflict",
|
|
212
|
-
"the campaign focus is genuinely ambiguous"
|
|
213
|
-
],
|
|
214
|
-
"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."
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
"action": "ask_source_intake_after_strategy_batch",
|
|
218
|
-
"artifact": "lead-source-intake.json",
|
|
219
|
-
"optional": true,
|
|
220
|
-
"skipWhen": "skip_strategy_packet_when_initial_context_is_sufficient matched",
|
|
221
|
-
"question": "How should we get the people for this campaign?",
|
|
222
|
-
"options": [
|
|
223
|
-
"Find people for me (recommended if you don't already have your own list)",
|
|
224
|
-
"I have a CSV of profiles to reach out to",
|
|
225
|
-
"I have a CSV of companies/domains I want to target"
|
|
226
|
-
],
|
|
227
|
-
"forbiddenOptionLabels": [
|
|
228
|
-
"engagers",
|
|
229
|
-
"titles",
|
|
230
|
-
"Signals",
|
|
231
|
-
"Sales Nav",
|
|
232
|
-
"Prospeo",
|
|
233
|
-
"search LinkedIn posts"
|
|
234
|
-
],
|
|
235
|
-
"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.",
|
|
236
|
-
"customInput": true,
|
|
237
|
-
"multiSelect": false,
|
|
238
|
-
"lastQuestionInFirstStrategyBatch": true
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
"action": "render_post_intake_progress_preamble",
|
|
242
|
-
"after": "founder_strategy_source_packet_answered",
|
|
243
|
-
"requiredVisibleContent": [
|
|
244
|
-
"turn this into a campaign brief",
|
|
245
|
-
"create the campaign shell with the brief already in it",
|
|
246
|
-
"watch the draft campaign as it fills in",
|
|
247
|
-
"no leads import and nothing sends yet"
|
|
248
|
-
],
|
|
249
|
-
"forbiddenWording": [
|
|
250
|
-
"brief.md",
|
|
251
|
-
"lead-review.md",
|
|
252
|
-
"lead-sample.json",
|
|
253
|
-
"message-validation.md"
|
|
254
156
|
]
|
|
255
157
|
},
|
|
256
158
|
{
|
|
257
|
-
"action": "
|
|
258
|
-
"
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
"
|
|
262
|
-
"requiredVisibleContent": [
|
|
263
|
-
"Campaign brief",
|
|
264
|
-
"Decision",
|
|
265
|
-
"Target",
|
|
266
|
-
"Pain",
|
|
267
|
-
"Offer",
|
|
268
|
-
"Proof",
|
|
269
|
-
"Lead plan",
|
|
270
|
-
"Risks",
|
|
271
|
-
"What happens next"
|
|
272
|
-
],
|
|
273
|
-
"mustRunBefore": ["optional_debug_artifact_writer", "Bash", "mkdir"],
|
|
274
|
-
"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."
|
|
275
|
-
},
|
|
276
|
-
{
|
|
277
|
-
"action": "optional_debug_artifact_writer",
|
|
278
|
-
"artifact": "brief.md",
|
|
279
|
-
"mode": "debug_or_uat_only",
|
|
280
|
-
"shouldNotRunInNormalCustomerPath": true,
|
|
281
|
-
"shouldNotBlockMainThread": true,
|
|
282
|
-
"allowedToRunWhileUserReviewsInlineBrief": true,
|
|
283
|
-
"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.",
|
|
284
|
-
"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
|
|
285
164
|
},
|
|
286
165
|
{
|
|
287
166
|
"action": "create_watchable_campaign_shell_with_v1_brief",
|
|
288
167
|
"tool": "create_campaign",
|
|
289
|
-
"artifact": "campaign-shell.json",
|
|
290
|
-
"when": "after_v1_brief_is_visible_and_before_brief_review",
|
|
291
|
-
"mode": "shell-first-campaign",
|
|
292
168
|
"requiredFields": [
|
|
293
169
|
"name",
|
|
294
170
|
"campaignBrief",
|
|
@@ -298,195 +174,110 @@
|
|
|
298
174
|
],
|
|
299
175
|
"requiredValues": {
|
|
300
176
|
"currentStep": "create-offer",
|
|
301
|
-
"watchNarration.stage": "brief
|
|
177
|
+
"watchNarration.stage": "brief"
|
|
302
178
|
},
|
|
303
|
-
"
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
"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.",
|
|
307
|
-
"onFailure": "stop_and_surface_campaign_shell_creation_error; no no-shell mint fallback in shell-first flow",
|
|
308
|
-
"forbiddenUntilRubricAndMessageReady": [
|
|
309
|
-
"import_leads",
|
|
310
|
-
"confirm_lead_list",
|
|
311
|
-
"queue_cells",
|
|
312
|
-
"enrich_with_prospeo",
|
|
313
|
-
"bulk_enrich_with_prospeo"
|
|
179
|
+
"capture": [
|
|
180
|
+
"campaignId",
|
|
181
|
+
"watchUrl"
|
|
314
182
|
],
|
|
315
|
-
"forbiddenUntilSenderAndSequenceReady": ["start_campaign"],
|
|
316
183
|
"canonicalStateWrites": [
|
|
317
184
|
"campaignId",
|
|
318
185
|
"watchUrl",
|
|
319
186
|
"campaignBrief",
|
|
320
|
-
"currentStep:create-offer"
|
|
321
|
-
"watchNarration: brief-review with approve-the-brief guidance"
|
|
187
|
+
"currentStep:create-offer"
|
|
322
188
|
]
|
|
323
189
|
},
|
|
324
190
|
{
|
|
325
191
|
"action": "surface_campaign_shell_watch_link",
|
|
326
|
-
"reference": "references/watch-link-handoff.md",
|
|
327
|
-
"requires": ["campaignId", "watchUrl", "campaignBrief"],
|
|
328
|
-
"requiredVisibleContent": [
|
|
329
|
-
"draft campaign shell",
|
|
330
|
-
"brief is already there",
|
|
331
|
-
"watch it fill in",
|
|
332
|
-
"no leads import and nothing sends yet",
|
|
333
|
-
"Watch link:"
|
|
334
|
-
],
|
|
335
|
-
"requiresCampaignState": ["campaignId", "watchUrl", "campaignBrief"],
|
|
336
192
|
"watchUrlSource": "create_campaign.watchUrl",
|
|
337
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.",
|
|
338
195
|
"codexBrowserHandoff": {
|
|
339
196
|
"openWhenAvailable": false,
|
|
340
197
|
"printWatchLinkOnly": true,
|
|
341
198
|
"tellUserCommandEnterOrClick": true,
|
|
342
199
|
"mustNotUseBrowserAutomation": true,
|
|
343
|
-
"fallbackMustNotClaimInspection": true
|
|
344
|
-
|
|
345
|
-
},
|
|
346
|
-
"immediateNextMainChatLine": "Cool, let's find leads."
|
|
200
|
+
"fallbackMustNotClaimInspection": true
|
|
201
|
+
}
|
|
347
202
|
}
|
|
348
203
|
],
|
|
349
|
-
"requiredArtifacts": [],
|
|
350
|
-
"producesArtifacts": [],
|
|
351
204
|
"allowedTools": [
|
|
352
205
|
"get_subskill_prompt",
|
|
353
|
-
"get_subskill_asset",
|
|
354
|
-
"get_auth_status",
|
|
355
|
-
"get_active_workspace",
|
|
356
|
-
"complete_sender_research",
|
|
357
206
|
"fetch_company",
|
|
358
207
|
"fetch_company_posts",
|
|
359
208
|
"fetch_linkedin_profile",
|
|
360
209
|
"fetch_linkedin_posts",
|
|
210
|
+
"complete_sender_research",
|
|
361
211
|
"create_campaign",
|
|
362
|
-
"update_campaign",
|
|
363
|
-
"WebFetch",
|
|
364
|
-
"WebSearch",
|
|
365
212
|
"AskUserQuestion",
|
|
366
213
|
"request_user_input"
|
|
367
214
|
],
|
|
368
215
|
"doNotAllow": [
|
|
216
|
+
"list_senders",
|
|
369
217
|
"save_rubrics",
|
|
370
218
|
"import_leads",
|
|
371
219
|
"confirm_lead_list",
|
|
372
220
|
"queue_cells",
|
|
373
|
-
"start_campaign"
|
|
374
|
-
|
|
375
|
-
|
|
221
|
+
"start_campaign"
|
|
222
|
+
],
|
|
223
|
+
"waitFor": [
|
|
224
|
+
"campaign_shell_created",
|
|
225
|
+
"brief_ready",
|
|
226
|
+
"confirm_with_user"
|
|
376
227
|
],
|
|
377
|
-
"watchRequired": false,
|
|
378
|
-
"waitFor": ["brief_ready", "campaign_shell_created", "confirm_with_user"],
|
|
379
228
|
"transitions": {
|
|
229
|
+
"campaign_shell_created": "brief-review",
|
|
380
230
|
"brief_ready": "brief-review",
|
|
381
|
-
"confirm_with_user": "brief-review"
|
|
382
|
-
|
|
383
|
-
},
|
|
384
|
-
"optionalProducesArtifacts": ["lead-source-intake.json"],
|
|
385
|
-
"debugProducesArtifacts": ["brief.md", "campaign-shell.json"]
|
|
231
|
+
"confirm_with_user": "brief-review"
|
|
232
|
+
}
|
|
386
233
|
},
|
|
387
234
|
{
|
|
388
235
|
"id": "brief-review",
|
|
389
236
|
"label": "Brief review",
|
|
390
237
|
"onEnter": [
|
|
391
238
|
{
|
|
392
|
-
"action": "
|
|
393
|
-
"
|
|
394
|
-
"fallbackDebugArtifact": "brief.md"
|
|
395
|
-
},
|
|
396
|
-
{
|
|
397
|
-
"action": "render_brief_approval_checkpoint",
|
|
398
|
-
"requiredVisibleContent": [
|
|
399
|
-
"Campaign brief",
|
|
400
|
-
"Who we are targeting",
|
|
401
|
-
"Why they should care",
|
|
402
|
-
"Offer / CTA",
|
|
403
|
-
"Proof to use",
|
|
404
|
-
"Lead source hypothesis",
|
|
405
|
-
"Message angle",
|
|
406
|
-
"Risks / assumptions",
|
|
407
|
-
"What happens next",
|
|
408
|
-
"approve this brief",
|
|
409
|
-
"revise the brief",
|
|
410
|
-
"then I will find good-fit leads"
|
|
411
|
-
],
|
|
412
|
-
"minimumVisibleBriefDetail": "full_readable_brief_before_question",
|
|
413
|
-
"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.",
|
|
414
|
-
"requiredCampaignLinks": ["watchUrl"],
|
|
415
|
-
"campaignLinkTiming": "before_approval_question",
|
|
416
|
-
"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.",
|
|
417
|
-
"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.",
|
|
418
|
-
"forbiddenNormalCustomerLinks": [
|
|
419
|
-
"brief.md",
|
|
420
|
-
"local draft path",
|
|
421
|
-
"Open artifact:"
|
|
422
|
-
],
|
|
423
|
-
"avoidQuestionWhenOnlyUsefulAnswerIs": "looks good"
|
|
424
|
-
},
|
|
425
|
-
{
|
|
426
|
-
"action": "ask_continue_or_revise_only_if_needed",
|
|
427
|
-
"requiresPriorVisibleContent": [
|
|
428
|
-
"full readable brief",
|
|
429
|
-
"live campaign shell orientation",
|
|
430
|
-
"Watch link: {watchUrl}"
|
|
431
|
-
],
|
|
432
|
-
"mustNotCallQuestionToolUntil": "The watch link has already been shown in normal chat text after create_campaign returned watchUrl.",
|
|
433
|
-
"autoContinueWhen": {
|
|
434
|
-
"artifactStatus": "confirmed",
|
|
435
|
-
"confidenceIn": ["high", "medium"],
|
|
436
|
-
"noOpenStrategicTradeoff": true,
|
|
437
|
-
"noMissingRequiredInputs": true
|
|
438
|
-
}
|
|
439
|
-
},
|
|
440
|
-
{
|
|
441
|
-
"action": "optional_debug_artifact_sync",
|
|
442
|
-
"artifacts": ["brief.md"],
|
|
443
|
-
"debugOrUatOnly": true,
|
|
444
|
-
"requiredBeforeTransition": false,
|
|
445
|
-
"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.",
|
|
446
|
-
"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"
|
|
447
241
|
},
|
|
448
242
|
{
|
|
449
|
-
"action": "
|
|
450
|
-
"
|
|
451
|
-
"
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
"
|
|
455
|
-
|
|
456
|
-
"watchNarration: find-leads with the first provider/lane being tested"
|
|
457
|
-
],
|
|
458
|
-
"fallback": "If campaignId is missing from CampaignOffer state, stop; shell-first flow requires an existing campaign before sourcing leads.",
|
|
459
|
-
"readsCampaignStateFirst": true,
|
|
460
|
-
"debugArtifacts": ["campaign-shell.json", "brief.md"]
|
|
243
|
+
"action": "ask_brief_choice",
|
|
244
|
+
"uses": "request_user_input",
|
|
245
|
+
"choices": [
|
|
246
|
+
"Approve brief",
|
|
247
|
+
"Revise brief",
|
|
248
|
+
"Pause here"
|
|
249
|
+
]
|
|
461
250
|
}
|
|
462
251
|
],
|
|
463
|
-
"
|
|
464
|
-
|
|
252
|
+
"requiredCampaignState": [
|
|
253
|
+
"campaignId",
|
|
254
|
+
"watchUrl",
|
|
255
|
+
"campaignBrief",
|
|
256
|
+
"currentStep"
|
|
257
|
+
],
|
|
465
258
|
"allowedTools": [
|
|
466
259
|
"AskUserQuestion",
|
|
467
260
|
"request_user_input",
|
|
468
|
-
"get_subskill_prompt",
|
|
469
261
|
"update_campaign"
|
|
470
262
|
],
|
|
471
263
|
"doNotAllow": [
|
|
472
264
|
"create_campaign",
|
|
473
|
-
"
|
|
265
|
+
"list_senders",
|
|
474
266
|
"import_leads",
|
|
475
267
|
"confirm_lead_list",
|
|
476
268
|
"queue_cells",
|
|
477
|
-
"start_campaign"
|
|
478
|
-
|
|
479
|
-
|
|
269
|
+
"start_campaign"
|
|
270
|
+
],
|
|
271
|
+
"waitFor": [
|
|
272
|
+
"user_brief_confirmed",
|
|
273
|
+
"revise_brief",
|
|
274
|
+
"auto_continue"
|
|
480
275
|
],
|
|
481
|
-
"watchRequired": false,
|
|
482
|
-
"waitFor": ["user_brief_confirmed", "revise_brief", "auto_continue"],
|
|
483
276
|
"transitions": {
|
|
484
277
|
"user_brief_confirmed": "find-leads",
|
|
485
278
|
"revise_brief": "brief-interview",
|
|
486
279
|
"auto_continue": "find-leads"
|
|
487
|
-
}
|
|
488
|
-
"interruptOnly": true,
|
|
489
|
-
"requiredCampaignState": ["campaignId", "campaignBrief", "currentStep"]
|
|
280
|
+
}
|
|
490
281
|
},
|
|
491
282
|
{
|
|
492
283
|
"id": "find-leads",
|
|
@@ -502,26 +293,8 @@
|
|
|
502
293
|
"people engaging with relevant LinkedIn posts",
|
|
503
294
|
"Sales Nav to find ICP people actively posting on LinkedIn",
|
|
504
295
|
"search by titles",
|
|
505
|
-
"Prospeo for a broader account/contact path
|
|
506
|
-
],
|
|
507
|
-
"sourceDirectionOverrides": {
|
|
508
|
-
"postEngagement": "signal-discovery",
|
|
509
|
-
"creatorOrCommentSignals": "signal-discovery",
|
|
510
|
-
"titlePersonaCompanyFilters": "sales-nav",
|
|
511
|
-
"hiringSignals": "prospeo",
|
|
512
|
-
"companyGrowthTriggers": "prospeo",
|
|
513
|
-
"targetAccountsOrDomains": "prospeo",
|
|
514
|
-
"suppliedProfilesOrCsv": "supplied-list",
|
|
515
|
-
"explicitCompare": "compare-requested-sources"
|
|
516
|
-
},
|
|
517
|
-
"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.",
|
|
518
|
-
"sourceFailureHandling": [
|
|
519
|
-
"timeout/error: try the next approved lane or ask the user to revise the source/target before import",
|
|
520
|
-
"zero raw results: try the next approved lane or ask the user to revise the source/target before import",
|
|
521
|
-
"weak ICP fit: try the next approved lane or ask the user to revise the source/target before import",
|
|
522
|
-
"weak message context: try the next approved lane or ask the user to revise the source/target before import"
|
|
296
|
+
"Prospeo for a broader account/contact path"
|
|
523
297
|
],
|
|
524
|
-
"allLanesFailedState": "revise-source",
|
|
525
298
|
"parallelAllowedOnlyWhen": [
|
|
526
299
|
"user explicitly requested source comparison",
|
|
527
300
|
"resuming already-started parallel scouts",
|
|
@@ -530,318 +303,117 @@
|
|
|
530
303
|
},
|
|
531
304
|
"onEnter": [
|
|
532
305
|
{
|
|
533
|
-
"action": "advance_watch_to_source_selection",
|
|
534
306
|
"tool": "update_campaign",
|
|
535
|
-
"requiredFields": ["campaignId", "currentStep", "watchNarration"],
|
|
536
307
|
"requiredValues": {
|
|
537
308
|
"currentStep": "pick-provider",
|
|
538
309
|
"watchNarration.stage": "find-leads"
|
|
539
310
|
},
|
|
540
|
-
"
|
|
541
|
-
"requiresVisibleCheckpointBeforeProviderLane": true,
|
|
542
|
-
"askApprovalBeforeFirstLane": true,
|
|
543
|
-
"forbidDirectPlanToProviderLane": true,
|
|
544
|
-
"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."
|
|
545
|
-
},
|
|
546
|
-
{
|
|
547
|
-
"action": "advance_watch_to_initial_source_lane",
|
|
548
|
-
"tool": "update_campaign",
|
|
549
|
-
"requiredFields": ["campaignId", "currentStep", "watchNarration"],
|
|
550
|
-
"currentStepByPrimaryLane": {
|
|
551
|
-
"signals": "signal-discovery",
|
|
552
|
-
"salesNav": "sales-nav",
|
|
553
|
-
"prospeo": "prospeo",
|
|
554
|
-
"apollo": "apollo-ai",
|
|
555
|
-
"existingList": "saved-lists",
|
|
556
|
-
"uploadedDomains": "prospeo"
|
|
557
|
-
},
|
|
558
|
-
"when": "after_source_selection_checkpoint_before_first_source_attempt",
|
|
559
|
-
"requiresPriorVisibleStep": "pick-provider",
|
|
560
|
-
"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."
|
|
561
|
-
},
|
|
562
|
-
{
|
|
563
|
-
"action": "run_first_campaign_attached_source_search",
|
|
564
|
-
"requiredFields": ["campaignOfferId", "currentStep"],
|
|
565
|
-
"before": "evaluating_source_viability_gate",
|
|
566
|
-
"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."
|
|
311
|
+
"purpose": "show the visible source-selection checkpoint before provider lanes"
|
|
567
312
|
},
|
|
568
313
|
{
|
|
569
|
-
"
|
|
570
|
-
"
|
|
571
|
-
"good fit and active enough to be worth a LinkedIn test",
|
|
572
|
-
"campaign source step",
|
|
573
|
-
"primary source",
|
|
574
|
-
"source hypothesis",
|
|
575
|
-
"why this source now",
|
|
576
|
-
"quick viability gate",
|
|
577
|
-
"expected volume",
|
|
578
|
-
"sampled ICP fit",
|
|
579
|
-
"activity/warmth signal",
|
|
580
|
-
"cleanup risk",
|
|
581
|
-
"tradeoffs",
|
|
582
|
-
"search lanes",
|
|
583
|
-
"timeframe",
|
|
584
|
-
"sample size",
|
|
585
|
-
"estimated usable leads",
|
|
586
|
-
"source decision + sample",
|
|
587
|
-
"no import or enrichment yet"
|
|
588
|
-
],
|
|
589
|
-
"watchNarrationRule": "Do not include time estimates. Use current, campaign-specific search reasoning instead."
|
|
314
|
+
"tool": "get_source_scout_registry",
|
|
315
|
+
"purpose": "load canonical source scout names before optional branch launch"
|
|
590
316
|
},
|
|
591
317
|
{
|
|
592
|
-
"action": "
|
|
593
|
-
"
|
|
594
|
-
|
|
595
|
-
"
|
|
596
|
-
"
|
|
597
|
-
"supplied-domains",
|
|
598
|
-
"existing-lead-list"
|
|
318
|
+
"action": "run_sequential_source_funnel",
|
|
319
|
+
"defaultOrder": [
|
|
320
|
+
"source-scout-linkedin-engagement",
|
|
321
|
+
"source-scout-sales-nav",
|
|
322
|
+
"source-scout-prospeo-contact"
|
|
599
323
|
],
|
|
600
|
-
"
|
|
601
|
-
|
|
602
|
-
{
|
|
603
|
-
"action": "run_subskill",
|
|
604
|
-
"target": "find-leads",
|
|
605
|
-
"mode": "campaign-attached-required",
|
|
606
|
-
"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."
|
|
607
|
-
},
|
|
608
|
-
{
|
|
609
|
-
"action": "optional_debug_artifacts",
|
|
610
|
-
"artifacts": ["lead-review.md", "lead-sample.json"],
|
|
611
|
-
"debugOrUatOnly": true,
|
|
612
|
-
"shouldNotRunInNormalCustomerPath": true,
|
|
613
|
-
"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
|
|
614
326
|
}
|
|
615
327
|
],
|
|
616
|
-
"
|
|
617
|
-
|
|
328
|
+
"requiredCampaignState": [
|
|
329
|
+
"campaignId",
|
|
330
|
+
"campaignBrief",
|
|
331
|
+
"currentStep"
|
|
332
|
+
],
|
|
618
333
|
"allowedTools": [
|
|
619
|
-
"
|
|
620
|
-
"get_subskill_asset",
|
|
334
|
+
"get_source_scout_registry",
|
|
621
335
|
"get_provider_prompt",
|
|
622
336
|
"lookup_sales_nav_filter",
|
|
623
337
|
"search_sales_nav",
|
|
624
338
|
"search_prospeo",
|
|
625
339
|
"search_signals",
|
|
340
|
+
"select_promising_posts",
|
|
626
341
|
"fetch_post_engagers",
|
|
627
342
|
"fetch_company",
|
|
628
343
|
"fetch_linkedin_profile",
|
|
629
|
-
"AskUserQuestion",
|
|
630
|
-
"request_user_input",
|
|
631
344
|
"load_csv_linkedin_leads",
|
|
632
345
|
"load_csv_domains",
|
|
633
346
|
"get_rows_minimal",
|
|
634
|
-
"update_campaign"
|
|
347
|
+
"update_campaign",
|
|
348
|
+
"AskUserQuestion",
|
|
349
|
+
"request_user_input"
|
|
635
350
|
],
|
|
636
351
|
"doNotAllow": [
|
|
637
352
|
"create_campaign",
|
|
353
|
+
"list_senders",
|
|
638
354
|
"save_rubrics",
|
|
639
355
|
"import_leads",
|
|
640
356
|
"confirm_lead_list",
|
|
641
357
|
"queue_cells",
|
|
642
|
-
"start_campaign"
|
|
643
|
-
|
|
644
|
-
|
|
358
|
+
"start_campaign"
|
|
359
|
+
],
|
|
360
|
+
"waitFor": [
|
|
361
|
+
"lead_review_ready",
|
|
362
|
+
"revise_brief",
|
|
363
|
+
"confirm_with_user"
|
|
645
364
|
],
|
|
646
|
-
"watchRequired": false,
|
|
647
|
-
"waitFor": ["lead_review_ready", "revise_brief", "confirm_with_user"],
|
|
648
365
|
"transitions": {
|
|
649
366
|
"lead_review_ready": "lead-review",
|
|
650
367
|
"revise_brief": "brief-interview",
|
|
651
368
|
"confirm_with_user": "lead-review"
|
|
652
|
-
}
|
|
653
|
-
"optionalRequiredArtifacts": ["lead-source-intake.json"],
|
|
654
|
-
"toolRules": {
|
|
655
|
-
"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.",
|
|
656
|
-
"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.",
|
|
657
|
-
"existingLeadList": "Sample existing rows before import; preserve the existing list as selectedLeadListId source state and do not clone/import until auto-execute-leads.",
|
|
658
|
-
"forbiddenPreImport": [
|
|
659
|
-
"import_leads",
|
|
660
|
-
"confirm_lead_list",
|
|
661
|
-
"queue_cells",
|
|
662
|
-
"enrich_with_prospeo",
|
|
663
|
-
"bulk_enrich_with_prospeo",
|
|
664
|
-
"start_campaign",
|
|
665
|
-
"save_domain_filters"
|
|
666
|
-
],
|
|
667
|
-
"providerCampaignOfferIdRequiredFor": [
|
|
668
|
-
"get_provider_prompt",
|
|
669
|
-
"search_signals",
|
|
670
|
-
"search_sales_nav",
|
|
671
|
-
"search_prospeo",
|
|
672
|
-
"import_leads",
|
|
673
|
-
"selected source state"
|
|
674
|
-
]
|
|
675
|
-
},
|
|
676
|
-
"requiredCampaignState": ["campaignId", "campaignBrief", "currentStep"],
|
|
677
|
-
"debugProducesArtifacts": ["lead-review.md", "lead-sample.json"]
|
|
369
|
+
}
|
|
678
370
|
},
|
|
679
371
|
{
|
|
680
372
|
"id": "lead-review",
|
|
681
|
-
"label": "
|
|
373
|
+
"label": "Source approval",
|
|
682
374
|
"onEnter": [
|
|
683
375
|
{
|
|
684
|
-
"action": "
|
|
685
|
-
"
|
|
686
|
-
|
|
687
|
-
"
|
|
688
|
-
"
|
|
689
|
-
"Math",
|
|
690
|
-
"Eligible posts",
|
|
691
|
-
"Sample",
|
|
692
|
-
"ICP-fit",
|
|
693
|
-
"Good-fit / 100 engagers",
|
|
694
|
-
"Required engagers",
|
|
695
|
-
"Avg engagers/post",
|
|
696
|
-
"Good-fit / post",
|
|
697
|
-
"Source target",
|
|
698
|
-
"Posts needed",
|
|
699
|
-
"Selected",
|
|
700
|
-
"Review batch",
|
|
701
|
-
"Expected good-fit leads",
|
|
702
|
-
"Scale option",
|
|
703
|
-
"Why this source"
|
|
704
|
-
],
|
|
705
|
-
"signalsFirstRequiredFields": [
|
|
706
|
-
"post URL",
|
|
707
|
-
"post author",
|
|
708
|
-
"posted date or recency",
|
|
709
|
-
"topic or excerpt",
|
|
710
|
-
"engagement or estimated engagers",
|
|
711
|
-
"sampled engagers",
|
|
712
|
-
"sampled fits",
|
|
713
|
-
"sampled fits as n/N",
|
|
714
|
-
"estimated usable leads",
|
|
715
|
-
"why use or discard"
|
|
716
|
-
],
|
|
717
|
-
"evidenceSnapshotRequiredFields": [
|
|
718
|
-
"provider/source angle label",
|
|
719
|
-
"source lane or keyword",
|
|
720
|
-
"timeframe searched",
|
|
721
|
-
"raw results found",
|
|
722
|
-
"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",
|
|
723
381
|
"sampled people",
|
|
724
|
-
"sampled fits as n/N plus percentage
|
|
725
|
-
"estimated usable
|
|
726
|
-
"
|
|
727
|
-
"
|
|
728
|
-
]
|
|
729
|
-
"sourceDecisionRequiredFields": [
|
|
730
|
-
"primary source",
|
|
731
|
-
"exact Sales Nav filters or source recipe",
|
|
732
|
-
"runner-up source",
|
|
733
|
-
"why runner-up lost",
|
|
734
|
-
"what approval means"
|
|
735
|
-
],
|
|
736
|
-
"approvalMathRequiredFields": [
|
|
737
|
-
"selected or relevant posts count",
|
|
738
|
-
"eligible right-content posts count",
|
|
739
|
-
"reachable engagers count",
|
|
740
|
-
"sampled engagers count",
|
|
741
|
-
"sampled ICP fits as n/N plus percentage or range",
|
|
742
|
-
"good-fit prospects per 100 engagers",
|
|
743
|
-
"required engagers to scrape",
|
|
744
|
-
"average reachable engagers per post",
|
|
745
|
-
"expected good-fit prospects per post after cleanup",
|
|
746
|
-
"dedupe or cleanup factor",
|
|
747
|
-
"source target good-fit lead count default 300",
|
|
748
|
-
"posts needed for target",
|
|
749
|
-
"selected posts count",
|
|
750
|
-
"15-row review-batch import limit",
|
|
751
|
-
"estimated usable prospects range",
|
|
752
|
-
"scale alternative source",
|
|
753
|
-
"scale alternative raw or preview volume",
|
|
754
|
-
"scale alternative sampled usable rows as n/N plus percentage or range",
|
|
755
|
-
"Sales Nav broadening or loosening attempts when fallback volume is too tight",
|
|
756
|
-
"warmth or message-context tradeoff",
|
|
757
|
-
"what to choose if the user wants more volume"
|
|
758
|
-
],
|
|
759
|
-
"signalsInlineTableRequiredFields": [
|
|
760
|
-
"keyword lane",
|
|
761
|
-
"timeframe",
|
|
762
|
-
"posts found",
|
|
763
|
-
"finalist posts reviewed",
|
|
764
|
-
"post URL or title",
|
|
765
|
-
"engagers or engagement count",
|
|
766
|
-
"sampled engagers",
|
|
767
|
-
"good fits as n/N",
|
|
768
|
-
"estimated usable prospects per post",
|
|
769
|
-
"use or discard decision"
|
|
770
|
-
],
|
|
771
|
-
"forbidPercentOnlyFitRates": true,
|
|
772
|
-
"requiredArtifactLinks": ["lead-review.md"],
|
|
773
|
-
"artifactLinkTiming": "before_next_step_or_revision_question",
|
|
774
|
-
"doNotCompressToSummaryOnly": false,
|
|
775
|
-
"doNotRenderArtifactLinksOnly": true,
|
|
776
|
-
"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.",
|
|
777
|
-
"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."
|
|
778
|
-
},
|
|
779
|
-
{
|
|
780
|
-
"action": "render_post_lead_parallel_progress",
|
|
781
|
-
"requiredVisibleContent": [
|
|
782
|
-
"Lead source is set",
|
|
783
|
-
"campaign is on the primary source step",
|
|
784
|
-
"Tighten the fit filter",
|
|
785
|
-
"Message generation",
|
|
786
|
-
"approved brief and real sample leads",
|
|
787
|
-
"no import or enrichment until rubrics and message set are ready",
|
|
788
|
-
"parallel only if real parallel branches were launched",
|
|
789
|
-
"import the first 15-row review batch before fit/message work",
|
|
790
|
-
"selectedLeadListId stays the source list and workflowTableId is the campaign table"
|
|
791
|
-
],
|
|
792
|
-
"watchNarrationRule": "Do not include time estimates. Say what review-batch work is happening and what the user will approve next.",
|
|
793
|
-
"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.",
|
|
794
|
-
"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."
|
|
795
|
-
},
|
|
796
|
-
{
|
|
797
|
-
"action": "ask_continue_revise_or_confirm_only_if_needed",
|
|
798
|
-
"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'.",
|
|
799
|
-
"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.",
|
|
800
|
-
"autoContinueWhen": {
|
|
801
|
-
"status": "confirmed",
|
|
802
|
-
"confidenceIn": ["high", "medium"],
|
|
803
|
-
"projectedGoodFitsAtLeast": 150,
|
|
804
|
-
"samplePassRateAtLeast": 0.7,
|
|
805
|
-
"noProviderMismatch": true,
|
|
806
|
-
"noStrategicTradeoff": true
|
|
807
|
-
}
|
|
382
|
+
"sampled fits as n/N plus percentage/range",
|
|
383
|
+
"estimated usable prospects",
|
|
384
|
+
"cleanup risk",
|
|
385
|
+
"what approval authorizes"
|
|
386
|
+
]
|
|
808
387
|
},
|
|
809
388
|
{
|
|
810
|
-
"action": "
|
|
811
|
-
"
|
|
812
|
-
"
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
"
|
|
816
|
-
|
|
817
|
-
"providerSearchAssociation",
|
|
818
|
-
"watchNarration only when paired to an already-visible source recommendation; do not create a separate source-approved navigation beat before import",
|
|
819
|
-
"selectedLeadListId as source list id only for existing-list or supplied-list preview"
|
|
820
|
-
],
|
|
821
|
-
"sourceApprovalWatchRule": "Immediately after the user approves a source, persist the approved source as the active provider on the CampaignOffer without a separate source-approved currentStep fix. If the recommendation already switched the watched source lane before approval, leave it there; the next visible navigation after approval is owned by import_leads after it has a leadListId/jobId. Apply the same rule for signal-discovery, sales-nav, and prospeo approvals.",
|
|
822
|
-
"fallback": "Stop if campaignId is missing; the source must be attached to the existing CampaignOffer before import.",
|
|
823
|
-
"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
|
+
]
|
|
824
396
|
}
|
|
825
397
|
],
|
|
826
|
-
"
|
|
827
|
-
|
|
398
|
+
"requiredCampaignState": [
|
|
399
|
+
"campaignId",
|
|
400
|
+
"campaignBrief",
|
|
401
|
+
"providerSearchAssociation"
|
|
402
|
+
],
|
|
828
403
|
"allowedTools": [
|
|
829
404
|
"AskUserQuestion",
|
|
830
405
|
"request_user_input",
|
|
831
|
-
"get_subskill_prompt",
|
|
832
406
|
"update_campaign"
|
|
833
407
|
],
|
|
834
408
|
"doNotAllow": [
|
|
835
409
|
"create_campaign",
|
|
410
|
+
"list_senders",
|
|
836
411
|
"save_rubrics",
|
|
837
412
|
"import_leads",
|
|
838
413
|
"confirm_lead_list",
|
|
839
414
|
"queue_cells",
|
|
840
|
-
"start_campaign"
|
|
841
|
-
"enrich_with_prospeo",
|
|
842
|
-
"bulk_enrich_with_prospeo"
|
|
415
|
+
"start_campaign"
|
|
843
416
|
],
|
|
844
|
-
"watchRequired": false,
|
|
845
417
|
"waitFor": [
|
|
846
418
|
"lead_review_confirmed",
|
|
847
419
|
"revise_leads",
|
|
@@ -853,188 +425,80 @@
|
|
|
853
425
|
"revise_leads": "find-leads",
|
|
854
426
|
"confirm_with_user": "auto-execute-leads",
|
|
855
427
|
"auto_continue": "auto-execute-leads"
|
|
856
|
-
}
|
|
857
|
-
"interruptOnly": true,
|
|
858
|
-
"requiredCampaignState": [
|
|
859
|
-
"campaignId",
|
|
860
|
-
"campaignBrief",
|
|
861
|
-
"providerSearchAssociation"
|
|
862
|
-
]
|
|
428
|
+
}
|
|
863
429
|
},
|
|
864
430
|
{
|
|
865
431
|
"id": "auto-execute-leads",
|
|
866
|
-
"label": "
|
|
867
|
-
"currentStepValue":
|
|
868
|
-
"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",
|
|
869
434
|
"reference": "references/step-13-import-leads.md",
|
|
870
435
|
"onEnter": [
|
|
871
436
|
{
|
|
872
|
-
"
|
|
873
|
-
"
|
|
874
|
-
|
|
875
|
-
"branches": {
|
|
876
|
-
"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.",
|
|
877
|
-
"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 }).",
|
|
878
|
-
"existing-lead-list": "Use the campaign-attached existingLeadListId as selectedLeadListId and call confirm_lead_list({ sourceLeadListId: existingLeadListId, targetLeadCount: import.importLimit }).",
|
|
879
|
-
"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"
|
|
880
440
|
},
|
|
881
|
-
"
|
|
882
|
-
"leadListId",
|
|
883
|
-
"domainFilterId",
|
|
884
|
-
"searchId",
|
|
885
|
-
"selectedLeadListId",
|
|
886
|
-
"workflowTableId",
|
|
887
|
-
"importedRowIds"
|
|
888
|
-
],
|
|
889
|
-
"onSourceFileChanged": "escalate_before_materialization",
|
|
890
|
-
"onLowDomainYield": "confirm-with-user: widen role filters, add more domains, or abort; never drop domainFilterId silently",
|
|
891
|
-
"preconditions": [
|
|
892
|
-
"campaignId exists",
|
|
893
|
-
"providerSearchAssociation or selected source state exists"
|
|
894
|
-
],
|
|
895
|
-
"onMissingCampaignAttachedSource": "stop_before_import_and_route_to_find_leads; source scouts must attach searches/selections with campaignOfferId before Step 13"
|
|
896
|
-
},
|
|
897
|
-
{
|
|
898
|
-
"action": "watch_mode_orient",
|
|
899
|
-
"watchNarrationRule": "Before import_leads starts, keep the guide aligned with the already-approved source without creating a separate source-approved step fix. Persist the approved source provider if needed, but 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 import progress copy only once the owning tool has a table/job to show; include a no-launch safety note."
|
|
441
|
+
"purpose": "load tail contract before execution tools"
|
|
900
442
|
},
|
|
901
443
|
{
|
|
902
444
|
"tool": "import_leads",
|
|
903
|
-
"
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
"targetLeadCountFromConfig": "sourceTargetGoodFitLeadCount (default 300) for provider source-list materialization, not import.importLimit",
|
|
908
|
-
"signalDiscoveryRequiredFields": [
|
|
909
|
-
"targetEngagerCount from approved source math",
|
|
910
|
-
"approved promoted post ids selected with select_promising_posts",
|
|
911
|
-
"maxPostsToScrape from approved source math"
|
|
445
|
+
"requiredFields": [
|
|
446
|
+
"campaignOfferId",
|
|
447
|
+
"selected source/list",
|
|
448
|
+
"importLimit"
|
|
912
449
|
],
|
|
913
|
-
"
|
|
914
|
-
|
|
450
|
+
"requiredValues": {
|
|
451
|
+
"importLimit": 15
|
|
452
|
+
},
|
|
915
453
|
"modeAddHandshake": {
|
|
916
|
-
"firstCallReturns": "needsModeSelection
|
|
917
|
-
"
|
|
918
|
-
"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"
|
|
919
456
|
},
|
|
920
|
-
"surfaceDedupRatio": true
|
|
921
|
-
"defaultBranch": "normal-discovery",
|
|
922
|
-
"skipWhen": "resolved source branch returns sourceLeadListId for confirm_lead_list",
|
|
923
|
-
"requiredBeforeCall": [
|
|
924
|
-
"campaign_attached_source_state",
|
|
925
|
-
"for Signal Discovery: approved_promoted_posts_attached_to_campaign"
|
|
926
|
-
]
|
|
457
|
+
"surfaceDedupRatio": true
|
|
927
458
|
},
|
|
928
459
|
{
|
|
929
|
-
"tool": "wait_for_lead_list_ready"
|
|
930
|
-
"sourceBranches": ["normal-discovery", "supplied-domains"],
|
|
931
|
-
"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"
|
|
932
461
|
},
|
|
933
462
|
{
|
|
934
463
|
"tool": "confirm_lead_list",
|
|
935
|
-
"
|
|
936
|
-
|
|
937
|
-
"
|
|
938
|
-
"
|
|
939
|
-
"supplied-linkedin-profiles",
|
|
940
|
-
"existing-lead-list"
|
|
464
|
+
"requiredFields": [
|
|
465
|
+
"campaignOfferId",
|
|
466
|
+
"selectedLeadListId",
|
|
467
|
+
"reviewBatchLimit"
|
|
941
468
|
],
|
|
942
|
-
"
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
469
|
+
"capture": [
|
|
470
|
+
"workflowTableId",
|
|
471
|
+
"reviewBatchRowIds"
|
|
472
|
+
]
|
|
946
473
|
},
|
|
947
474
|
{
|
|
948
|
-
"tool": "wait_for_campaign_table_ready"
|
|
949
|
-
"purpose": "wait_for_campaign_table_rows_after_confirm"
|
|
475
|
+
"tool": "wait_for_campaign_table_ready"
|
|
950
476
|
},
|
|
951
477
|
{
|
|
952
478
|
"tool": "get_rows_minimal",
|
|
953
|
-
"
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
},
|
|
957
|
-
{
|
|
958
|
-
"action": "require_non_empty_review_batch_before_filter_choice",
|
|
959
|
-
"after": "get_rows_minimal",
|
|
960
|
-
"blocksCurrentStep": "filter-choice",
|
|
961
|
-
"onZeroRows": "source-import-recovery",
|
|
962
|
-
"recoveryChoices": [
|
|
963
|
-
"retry import",
|
|
964
|
-
"import more from approved source",
|
|
965
|
-
"revise source"
|
|
966
|
-
],
|
|
967
|
-
"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."
|
|
968
|
-
},
|
|
969
|
-
{
|
|
970
|
-
"tool": "get_post_find_leads_scout_registry",
|
|
971
|
-
"purpose": "load_post_import_message_draft_builder_registry",
|
|
972
|
-
"requiredBeforeMessageDraftLaunch": true
|
|
973
|
-
},
|
|
974
|
-
{
|
|
975
|
-
"action": "launch_message_draft_builder_after_review_batch_import",
|
|
976
|
-
"mode": "background_required_when_host_supports_subagents",
|
|
977
|
-
"registryRequired": "get_post_find_leads_scout_registry",
|
|
978
|
-
"branch": {
|
|
979
|
-
"name": "message-generation",
|
|
980
|
-
"target": "generate-messages",
|
|
981
|
-
"workerName": "post-find-leads-message-scout",
|
|
982
|
-
"inputs": [
|
|
983
|
-
"campaignBrief",
|
|
984
|
-
"selected source decision",
|
|
985
|
-
"selectedLeadListId source list",
|
|
986
|
-
"workflowTableId imported 15-row review batch"
|
|
987
|
-
],
|
|
988
|
-
"toolCallRequiredBeforeArtifacts": [
|
|
989
|
-
"get_subskill_prompt({ subskillName: \"generate-messages\" }) until hasMore=false"
|
|
990
|
-
],
|
|
991
|
-
"producesArtifacts": [
|
|
992
|
-
"template recommendation",
|
|
993
|
-
"token fill rules",
|
|
994
|
-
"rendered sample"
|
|
995
|
-
],
|
|
996
|
-
"optionalProducesArtifacts": [
|
|
997
|
-
"message-validation.md",
|
|
998
|
-
"message-prep.md",
|
|
999
|
-
"message-candidate-drafts.md"
|
|
1000
|
-
],
|
|
1001
|
-
"ownership": "proof inventory, token strategy, angle drafting, skeptical-prospect review, and selected winner only"
|
|
479
|
+
"requiredValues": {
|
|
480
|
+
"tableId": "{workflowTableId}",
|
|
481
|
+
"limit": 15
|
|
1002
482
|
},
|
|
1003
|
-
"
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
"runId or fallbackId",
|
|
1007
|
-
"statusSource",
|
|
1008
|
-
"status",
|
|
1009
|
-
"startedAt",
|
|
1010
|
-
"updatedAt",
|
|
1011
|
-
"basisToken",
|
|
1012
|
-
"basis.selectedLeadListId",
|
|
1013
|
-
"basis.workflowTableId",
|
|
1014
|
-
"basis.reviewBatchRowHash or basis.reviewBatchRowIds"
|
|
1015
|
-
],
|
|
1016
|
-
"basisFields": [
|
|
1017
|
-
"campaign revision or updatedAt",
|
|
1018
|
-
"brief hash",
|
|
1019
|
-
"selectedLeadListId",
|
|
1020
|
-
"workflowTableId",
|
|
1021
|
-
"bounded review-batch row ids/hash",
|
|
1022
|
-
"filter choice at branch start",
|
|
1023
|
-
"filter/rubric basis when present"
|
|
1024
|
-
],
|
|
1025
|
-
"chatAnnouncementRule": "After a live branch or explicit parent-thread fallback starts, tell the user the background Message Draft Builder is running from the full generate-messages prompt and the real review-batch contacts while they decide filters. Do not say it is running before runtime proof exists.",
|
|
1026
|
-
"racePrecedence": "ready output from the current basis wins; branch-superseded and fallback-superseded are ignored for display; spawn-failed, blocked, retry-needed, or stale show blocked/retry copy; fallback-active shows running only until a current branch-ready output supersedes it.",
|
|
1027
|
-
"rule": "Immediately after get_rows_minimal proves the bounded review batch is non-empty, start the Message Draft Builder from the live campaign brief, approved source, selectedLeadListId, and imported workflowTableId rows. Do this after confirm_lead_list succeeds and before any guide copy saying Message Draft Builder is In Progress. confirm_lead_list remains the first allowed start point; do not start from source recommendation, provider import job alone, or a zero-row review batch.",
|
|
1028
|
-
"fallback": "If the host cannot launch the post-find-leads-message-scout in the background, load the full generate-messages prompt in the parent thread and start the message-generation work with a fallbackId before reporting Message Draft Builder as In Progress. If message work cannot start, do not show running copy; surface pending/blocked template-start copy instead."
|
|
483
|
+
"capture": [
|
|
484
|
+
"reviewBatchRowHash"
|
|
485
|
+
]
|
|
1029
486
|
},
|
|
1030
487
|
{
|
|
1031
|
-
"action": "
|
|
1032
|
-
"
|
|
1033
|
-
"
|
|
488
|
+
"action": "launch_message_draft_builder_after_review_batch_import",
|
|
489
|
+
"tool": "get_post_find_leads_scout_registry",
|
|
490
|
+
"requiresNonEmptyRows": true
|
|
1034
491
|
}
|
|
1035
492
|
],
|
|
493
|
+
"requiredCampaignState": [
|
|
494
|
+
"campaignId",
|
|
495
|
+
"providerSearchAssociation",
|
|
496
|
+
"selectedLeadListId"
|
|
497
|
+
],
|
|
1036
498
|
"allowedTools": [
|
|
499
|
+
"get_subskill_prompt",
|
|
1037
500
|
"get_subskill_asset",
|
|
501
|
+
"get_post_find_leads_scout_registry",
|
|
1038
502
|
"import_leads",
|
|
1039
503
|
"wait_for_lead_list_ready",
|
|
1040
504
|
"confirm_lead_list",
|
|
@@ -1043,70 +507,50 @@
|
|
|
1043
507
|
"update_campaign",
|
|
1044
508
|
"AskUserQuestion",
|
|
1045
509
|
"request_user_input",
|
|
1046
|
-
"load_csv_linkedin_leads",
|
|
1047
|
-
"load_csv_domains",
|
|
1048
|
-
"get_provider_prompt",
|
|
1049
|
-
"get_campaign",
|
|
1050
|
-
"get_post_find_leads_scout_registry",
|
|
1051
|
-
"get_subskill_prompt",
|
|
1052
510
|
"Task",
|
|
1053
511
|
"spawn_agent"
|
|
1054
512
|
],
|
|
1055
513
|
"doNotAllow": [
|
|
514
|
+
"list_senders",
|
|
1056
515
|
"queue_cells",
|
|
1057
516
|
"start_campaign",
|
|
1058
517
|
"enrich_with_prospeo",
|
|
1059
518
|
"bulk_enrich_with_prospeo"
|
|
1060
519
|
],
|
|
1061
|
-
"watchRequired": true,
|
|
1062
520
|
"waitFor": "review_batch_imported",
|
|
1063
521
|
"transitions": {
|
|
1064
522
|
"review_batch_imported": "filter-choice",
|
|
1065
523
|
"escalation_triggered": "escalation"
|
|
1066
|
-
}
|
|
1067
|
-
"requiredArtifacts": [],
|
|
1068
|
-
"requiredCampaignState": [
|
|
1069
|
-
"campaignId",
|
|
1070
|
-
"providerSearchAssociation",
|
|
1071
|
-
"selectedLeadListId"
|
|
1072
|
-
]
|
|
524
|
+
}
|
|
1073
525
|
},
|
|
1074
526
|
{
|
|
1075
527
|
"id": "filter-choice",
|
|
1076
528
|
"label": "Filter choice",
|
|
1077
529
|
"currentStepValue": "filter-choice",
|
|
1078
|
-
"normalFlow": true,
|
|
1079
530
|
"onEnter": [
|
|
1080
|
-
{
|
|
1081
|
-
"action": "show_filter_choice",
|
|
1082
|
-
"requiredVisibleContent": [
|
|
1083
|
-
"Choose filters or skip",
|
|
1084
|
-
"Use filters to keep only qualified leads",
|
|
1085
|
-
"Skip filters and continue to message template review",
|
|
1086
|
-
"active filtering starts only after rubrics and the approved message template are saved"
|
|
1087
|
-
],
|
|
1088
|
-
"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."
|
|
1089
|
-
},
|
|
1090
531
|
{
|
|
1091
532
|
"tool": "update_campaign",
|
|
1092
533
|
"requiredValues": {
|
|
1093
534
|
"currentStep": "filter-choice",
|
|
1094
|
-
"watchNarration.stage": "
|
|
1095
|
-
}
|
|
1096
|
-
"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
|
+
}
|
|
1097
537
|
},
|
|
1098
538
|
{
|
|
1099
|
-
"action": "
|
|
1100
|
-
"
|
|
1101
|
-
"
|
|
1102
|
-
|
|
1103
|
-
"
|
|
1104
|
-
"
|
|
1105
|
-
|
|
1106
|
-
},
|
|
1107
|
-
"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
|
+
]
|
|
1108
546
|
}
|
|
1109
547
|
],
|
|
548
|
+
"requiredCampaignState": [
|
|
549
|
+
"campaignId",
|
|
550
|
+
"campaignBrief",
|
|
551
|
+
"selectedLeadListId",
|
|
552
|
+
"workflowTableId"
|
|
553
|
+
],
|
|
1110
554
|
"allowedTools": [
|
|
1111
555
|
"AskUserQuestion",
|
|
1112
556
|
"request_user_input",
|
|
@@ -1115,184 +559,87 @@
|
|
|
1115
559
|
],
|
|
1116
560
|
"doNotAllow": [
|
|
1117
561
|
"create_campaign",
|
|
1118
|
-
"
|
|
562
|
+
"list_senders",
|
|
1119
563
|
"import_leads",
|
|
1120
564
|
"confirm_lead_list",
|
|
1121
565
|
"queue_cells",
|
|
1122
566
|
"start_campaign",
|
|
1123
|
-
"generate_messages"
|
|
1124
|
-
|
|
1125
|
-
|
|
567
|
+
"generate_messages"
|
|
568
|
+
],
|
|
569
|
+
"waitFor": [
|
|
570
|
+
"filters_enabled",
|
|
571
|
+
"filters_skipped",
|
|
572
|
+
"revise_leads"
|
|
1126
573
|
],
|
|
1127
|
-
"watchRequired": true,
|
|
1128
|
-
"waitFor": ["filters_enabled", "filters_skipped", "revise_leads"],
|
|
1129
574
|
"transitions": {
|
|
1130
575
|
"filters_enabled": "post-lead-workstreams",
|
|
1131
576
|
"filters_skipped": "message-generation",
|
|
1132
577
|
"revise_leads": "find-leads"
|
|
1133
|
-
}
|
|
1134
|
-
"interruptOnly": true,
|
|
1135
|
-
"requiredCampaignState": [
|
|
1136
|
-
"campaignId",
|
|
1137
|
-
"campaignBrief",
|
|
1138
|
-
"selectedLeadListId",
|
|
1139
|
-
"workflowTableId"
|
|
1140
|
-
]
|
|
578
|
+
}
|
|
1141
579
|
},
|
|
1142
580
|
{
|
|
1143
581
|
"id": "post-lead-workstreams",
|
|
1144
|
-
"label": "
|
|
1145
|
-
"normalFlow": true,
|
|
582
|
+
"label": "Filter and message workstreams",
|
|
1146
583
|
"onEnter": [
|
|
1147
584
|
{
|
|
1148
585
|
"tool": "get_post_find_leads_scout_registry",
|
|
1149
|
-
"
|
|
1150
|
-
"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"
|
|
1151
587
|
},
|
|
1152
588
|
{
|
|
1153
|
-
"action": "
|
|
589
|
+
"action": "launch_or_reuse_post_lead_workstreams",
|
|
1154
590
|
"mode": "parallel_when_host_supports_subagents",
|
|
1155
|
-
"
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
"selected source decision",
|
|
1163
|
-
"selectedLeadListId",
|
|
1164
|
-
"workflowTableId review-batch rows"
|
|
1165
|
-
],
|
|
1166
|
-
"producesArtifacts": ["lead-filter.md"],
|
|
1167
|
-
"optionalProducesArtifacts": ["rubric.json"],
|
|
1168
|
-
"ownership": "lead quality, false-positive patterns, keep/exclude rules, and production rubric translation only"
|
|
1169
|
-
},
|
|
1170
|
-
{
|
|
1171
|
-
"name": "message-generation",
|
|
1172
|
-
"target": "generate-messages",
|
|
1173
|
-
"inputs": [
|
|
1174
|
-
"campaignBrief",
|
|
1175
|
-
"selected source decision",
|
|
1176
|
-
"selectedLeadListId",
|
|
1177
|
-
"workflowTableId review-batch rows"
|
|
1178
|
-
],
|
|
1179
|
-
"producesArtifacts": [
|
|
1180
|
-
"template recommendation",
|
|
1181
|
-
"token fill rules",
|
|
1182
|
-
"rendered sample"
|
|
1183
|
-
],
|
|
1184
|
-
"optionalProducesArtifacts": [
|
|
1185
|
-
"message-validation.md",
|
|
1186
|
-
"message-prep.md",
|
|
1187
|
-
"message-candidate-drafts.md"
|
|
1188
|
-
],
|
|
1189
|
-
"ownership": "proof inventory, token strategy, angle drafting, skeptical-prospect review, and selected winner only",
|
|
1190
|
-
"mode": "background_template_builder_reuse_or_launch_if_missing",
|
|
1191
|
-
"alreadyStartedBy": "auto-execute-leads.launch_message_draft_builder_after_review_batch_import"
|
|
1192
|
-
}
|
|
1193
|
-
],
|
|
1194
|
-
"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.",
|
|
1195
|
-
"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 with fallbackId before the next user-visible step. Message Draft Builder runtime proof must be stored under watchNarration.workerDetails.messageDraftBuilder with statusSource, status, startedAt, updatedAt, basisToken, and current selectedLeadListId/workflowTableId/review-batch basis. 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.",
|
|
1196
|
-
"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.",
|
|
1197
|
-
"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.",
|
|
1198
|
-
"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.",
|
|
1199
|
-
"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.",
|
|
1200
|
-
"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."
|
|
1201
|
-
},
|
|
1202
|
-
{
|
|
1203
|
-
"action": "wait_for_lead_filter_rules",
|
|
1204
|
-
"requiredArtifacts": ["lead-filter.md"],
|
|
1205
|
-
"optionalArtifacts": [
|
|
1206
|
-
"rubric.json",
|
|
1207
|
-
"message-validation.md",
|
|
1208
|
-
"message-prep.md",
|
|
1209
|
-
"message-candidate-drafts.md"
|
|
591
|
+
"inputs": [
|
|
592
|
+
"campaignId",
|
|
593
|
+
"campaignBrief",
|
|
594
|
+
"selectedLeadListId",
|
|
595
|
+
"workflowTableId",
|
|
596
|
+
"reviewBatchRowIds/hash",
|
|
597
|
+
"filterChoice"
|
|
1210
598
|
],
|
|
1211
|
-
"
|
|
599
|
+
"stateSource": "CampaignOffer and workflow table rows",
|
|
600
|
+
"debugFilesOptionalOnly": true
|
|
1212
601
|
},
|
|
1213
602
|
{
|
|
1214
603
|
"action": "save_filter_rubrics_to_campaign",
|
|
1215
604
|
"tool": "save_rubrics",
|
|
1216
|
-
"
|
|
1217
|
-
"
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
"requiredBeforeImport": false,
|
|
1221
|
-
"requiredFields": ["campaignOfferId", "leadScoringRubrics"],
|
|
1222
|
-
"writesCampaignState": "leadScoringRubrics",
|
|
1223
|
-
"requiredBeforeCascade": true
|
|
1224
|
-
},
|
|
1225
|
-
{
|
|
1226
|
-
"action": "advance_watch_to_filter_leads_after_rubrics_saved",
|
|
1227
|
-
"tool": "update_campaign",
|
|
1228
|
-
"requires": ["campaignId", "workflowTableId", "leadScoringRubrics"],
|
|
1229
|
-
"requiredValues": {
|
|
1230
|
-
"currentStep": "apply-icp-rubric",
|
|
1231
|
-
"enableICPFilters": true,
|
|
1232
|
-
"watchNarration.stage": "fit-message"
|
|
1233
|
-
},
|
|
1234
|
-
"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.",
|
|
1235
|
-
"when": "after_save_rubrics_succeeds_before_waiting_for_message_validation_or_queueing_enrichment",
|
|
1236
|
-
"writesCampaignState": "currentStep:apply-icp-rubric"
|
|
1237
|
-
},
|
|
1238
|
-
{
|
|
1239
|
-
"tool": "get_campaign_navigation_state",
|
|
1240
|
-
"purpose": "confirm the watched UI moved to Filter Leads after rubrics saved",
|
|
1241
|
-
"optional": true
|
|
1242
|
-
},
|
|
1243
|
-
{
|
|
1244
|
-
"action": "wait_for_message_draft_recommendation",
|
|
1245
|
-
"requiredOutputs": [
|
|
1246
|
-
"template recommendation",
|
|
1247
|
-
"token fill rules",
|
|
1248
|
-
"rendered sample"
|
|
1249
|
-
],
|
|
1250
|
-
"optionalArtifacts": [
|
|
1251
|
-
"message-validation.md",
|
|
1252
|
-
"message-prep.md",
|
|
1253
|
-
"message-candidate-drafts.md"
|
|
605
|
+
"when": "filters_enabled and rubrics are production-shaped",
|
|
606
|
+
"requiredFields": [
|
|
607
|
+
"campaignOfferId",
|
|
608
|
+
"leadScoringRubrics"
|
|
1254
609
|
],
|
|
1255
|
-
"
|
|
610
|
+
"writesCampaignState": "leadScoringRubrics"
|
|
1256
611
|
}
|
|
1257
612
|
],
|
|
1258
|
-
"
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
"
|
|
1262
|
-
"
|
|
1263
|
-
"message-candidate-drafts.md"
|
|
613
|
+
"requiredCampaignState": [
|
|
614
|
+
"campaignId",
|
|
615
|
+
"campaignBrief",
|
|
616
|
+
"selectedLeadListId",
|
|
617
|
+
"workflowTableId"
|
|
1264
618
|
],
|
|
1265
619
|
"allowedTools": [
|
|
1266
620
|
"get_subskill_prompt",
|
|
1267
621
|
"get_subskill_asset",
|
|
1268
622
|
"get_post_find_leads_scout_registry",
|
|
1269
623
|
"save_rubrics",
|
|
624
|
+
"get_campaign",
|
|
625
|
+
"get_rows_minimal",
|
|
1270
626
|
"update_campaign",
|
|
1271
627
|
"get_campaign_navigation_state",
|
|
1272
|
-
"Task",
|
|
1273
|
-
"spawn_agent",
|
|
1274
628
|
"AskUserQuestion",
|
|
1275
|
-
"request_user_input"
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
"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.",
|
|
1279
|
-
"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.",
|
|
1280
|
-
"Do not let filter-leads create a new message sample. Do not let message-generation fetch new prospects.",
|
|
1281
|
-
"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.",
|
|
1282
|
-
"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.",
|
|
1283
|
-
"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"
|
|
1284
632
|
],
|
|
1285
633
|
"doNotAllow": [
|
|
1286
634
|
"create_campaign",
|
|
635
|
+
"list_senders",
|
|
1287
636
|
"import_leads",
|
|
1288
637
|
"confirm_lead_list",
|
|
638
|
+
"queue_cells",
|
|
1289
639
|
"start_campaign",
|
|
1290
640
|
"check_rubric",
|
|
1291
|
-
"generate_messages"
|
|
1292
|
-
"enrich_with_prospeo",
|
|
1293
|
-
"bulk_enrich_with_prospeo"
|
|
641
|
+
"generate_messages"
|
|
1294
642
|
],
|
|
1295
|
-
"watchRequired": true,
|
|
1296
643
|
"waitFor": [
|
|
1297
644
|
"post_lead_workstreams_ready",
|
|
1298
645
|
"revise_leads",
|
|
@@ -1305,120 +652,33 @@
|
|
|
1305
652
|
"revise_rubric": "filter-rubric",
|
|
1306
653
|
"revise_messaging": "message-generation",
|
|
1307
654
|
"confirm_with_user": "message-review"
|
|
1308
|
-
}
|
|
1309
|
-
"interruptOnly": true,
|
|
1310
|
-
"requiredCampaignState": [
|
|
1311
|
-
"campaignId",
|
|
1312
|
-
"campaignBrief",
|
|
1313
|
-
"selectedLeadListId",
|
|
1314
|
-
"workflowTableId"
|
|
1315
|
-
],
|
|
1316
|
-
"debugProducesArtifacts": [
|
|
1317
|
-
"lead-filter.md",
|
|
1318
|
-
"message-validation.md",
|
|
1319
|
-
"rubric.json",
|
|
1320
|
-
"message-prep.md",
|
|
1321
|
-
"message-candidate-drafts.md"
|
|
1322
|
-
]
|
|
1323
|
-
},
|
|
1324
|
-
{
|
|
1325
|
-
"id": "messages-mode-choice",
|
|
1326
|
-
"label": "Messages mode choice",
|
|
1327
|
-
"currentStepValue": null,
|
|
1328
|
-
"normalFlow": false,
|
|
1329
|
-
"onEnter": [
|
|
1330
|
-
{
|
|
1331
|
-
"action": "legacy_resume_only_notice",
|
|
1332
|
-
"rule": "Do not show this question in normal create-campaign runs. Route to message-generation/message-review instead."
|
|
1333
|
-
}
|
|
1334
|
-
],
|
|
1335
|
-
"allowedTools": [
|
|
1336
|
-
"AskUserQuestion",
|
|
1337
|
-
"request_user_input",
|
|
1338
|
-
"update_campaign",
|
|
1339
|
-
"get_campaign_navigation_state"
|
|
1340
|
-
],
|
|
1341
|
-
"doNotAllow": [
|
|
1342
|
-
"create_campaign",
|
|
1343
|
-
"import_leads",
|
|
1344
|
-
"confirm_lead_list",
|
|
1345
|
-
"queue_cells",
|
|
1346
|
-
"start_campaign",
|
|
1347
|
-
"generate_messages",
|
|
1348
|
-
"enrich_with_prospeo",
|
|
1349
|
-
"bulk_enrich_with_prospeo"
|
|
1350
|
-
],
|
|
1351
|
-
"watchRequired": true,
|
|
1352
|
-
"waitFor": ["legacy_resume_only"],
|
|
1353
|
-
"transitions": {
|
|
1354
|
-
"legacy_resume_only": "message-generation"
|
|
1355
|
-
},
|
|
1356
|
-
"interruptOnly": true,
|
|
1357
|
-
"requiredCampaignState": [
|
|
1358
|
-
"campaignId",
|
|
1359
|
-
"campaignBrief",
|
|
1360
|
-
"selectedLeadListId",
|
|
1361
|
-
"workflowTableId"
|
|
1362
|
-
],
|
|
1363
|
-
"resumeOnly": true,
|
|
1364
|
-
"deprecated": true,
|
|
1365
|
-
"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
|
+
}
|
|
1366
656
|
},
|
|
1367
657
|
{
|
|
1368
658
|
"id": "filter-rubric",
|
|
1369
|
-
"label": "
|
|
659
|
+
"label": "Rubric revision",
|
|
1370
660
|
"onEnter": [
|
|
1371
661
|
{
|
|
1372
|
-
"
|
|
1373
|
-
"
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
"action": "write_artifacts",
|
|
1378
|
-
"artifacts": ["lead-filter.md"],
|
|
1379
|
-
"optionalArtifacts": ["rubric.json"]
|
|
1380
|
-
},
|
|
1381
|
-
{
|
|
1382
|
-
"action": "show_lead_filter_summary",
|
|
1383
|
-
"artifact": "lead-filter.md",
|
|
1384
|
-
"renderInlineSections": [
|
|
1385
|
-
"## Lead filter",
|
|
1386
|
-
"Keep",
|
|
1387
|
-
"Exclude",
|
|
1388
|
-
"Why",
|
|
1389
|
-
"Expected impact"
|
|
1390
|
-
],
|
|
1391
|
-
"requiredArtifactLinks": ["lead-filter.md"],
|
|
1392
|
-
"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
|
+
}
|
|
1393
667
|
},
|
|
1394
668
|
{
|
|
1395
|
-
"action": "save_filter_rubrics_to_campaign",
|
|
1396
669
|
"tool": "save_rubrics",
|
|
1397
|
-
"
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
"
|
|
1402
|
-
"requiredFields": ["campaignOfferId", "leadScoringRubrics"],
|
|
1403
|
-
"writesCampaignState": "leadScoringRubrics",
|
|
1404
|
-
"requiredBeforeCascade": true
|
|
1405
|
-
},
|
|
1406
|
-
{
|
|
1407
|
-
"action": "ask_revise_only_if_filter_is_not_confirmed",
|
|
1408
|
-
"autoContinueWhen": {
|
|
1409
|
-
"status": "confirmed",
|
|
1410
|
-
"decisionIn": ["continue", "confirmed"],
|
|
1411
|
-
"expectedUsableLeadsAtLeast": 150,
|
|
1412
|
-
"noHeavyFilteringWarning": true,
|
|
1413
|
-
"noCampaignMissRisk": true
|
|
1414
|
-
}
|
|
670
|
+
"requiredFields": [
|
|
671
|
+
"campaignOfferId",
|
|
672
|
+
"leadScoringRubrics"
|
|
673
|
+
],
|
|
674
|
+
"writesCampaignState": "leadScoringRubrics"
|
|
1415
675
|
}
|
|
1416
676
|
],
|
|
1417
|
-
"
|
|
1418
|
-
|
|
1419
|
-
|
|
677
|
+
"requiredCampaignState": [
|
|
678
|
+
"campaignId",
|
|
679
|
+
"workflowTableId"
|
|
680
|
+
],
|
|
1420
681
|
"allowedTools": [
|
|
1421
|
-
"get_subskill_prompt",
|
|
1422
682
|
"get_subskill_asset",
|
|
1423
683
|
"save_rubrics",
|
|
1424
684
|
"AskUserQuestion",
|
|
@@ -1426,16 +686,14 @@
|
|
|
1426
686
|
],
|
|
1427
687
|
"doNotAllow": [
|
|
1428
688
|
"create_campaign",
|
|
689
|
+
"list_senders",
|
|
1429
690
|
"import_leads",
|
|
1430
691
|
"confirm_lead_list",
|
|
1431
692
|
"update_campaign",
|
|
1432
693
|
"queue_cells",
|
|
1433
694
|
"start_campaign",
|
|
1434
|
-
"check_rubric"
|
|
1435
|
-
"enrich_with_prospeo",
|
|
1436
|
-
"bulk_enrich_with_prospeo"
|
|
695
|
+
"check_rubric"
|
|
1437
696
|
],
|
|
1438
|
-
"watchRequired": false,
|
|
1439
697
|
"waitFor": [
|
|
1440
698
|
"lead_filter_ready",
|
|
1441
699
|
"revise_leads",
|
|
@@ -1447,62 +705,54 @@
|
|
|
1447
705
|
"revise_leads": "find-leads",
|
|
1448
706
|
"confirm_with_user": "message-generation",
|
|
1449
707
|
"auto_continue": "message-generation"
|
|
1450
|
-
}
|
|
1451
|
-
"interruptOnly": true,
|
|
1452
|
-
"requiredCampaignState": ["campaignId", "workflowTableId"]
|
|
708
|
+
}
|
|
1453
709
|
},
|
|
1454
710
|
{
|
|
1455
711
|
"id": "message-generation",
|
|
1456
712
|
"label": "Message generation",
|
|
1457
713
|
"onEnter": [
|
|
1458
714
|
{
|
|
1459
|
-
"action": "
|
|
1460
|
-
"target": "
|
|
1461
|
-
"
|
|
1462
|
-
"sampleSource": "imported review-batch rows from selectedLeadListId",
|
|
1463
|
-
"toolCallRequiredBeforeArtifacts": [
|
|
715
|
+
"action": "run_or_reconcile_message_draft_builder",
|
|
716
|
+
"target": "post-find-leads-message-scout",
|
|
717
|
+
"toolCallRequiredBeforeDraft": [
|
|
1464
718
|
"get_subskill_prompt({ subskillName: \"generate-messages\", offset, limit }) until hasMore=false",
|
|
1465
719
|
"optional supplemental check: get_subskill_asset({ subskillName: \"create-campaign-v2\", assetPath: \"references/message-review-safety-gate.md\" })"
|
|
1466
720
|
],
|
|
1467
|
-
"
|
|
1468
|
-
"
|
|
1469
|
-
},
|
|
1470
|
-
{
|
|
1471
|
-
"action": "return_template_recommendation",
|
|
1472
|
-
"optionalArtifact": "message-validation.md"
|
|
721
|
+
"stateSource": "campaignBrief, selected source state, selectedLeadListId, workflowTableId, bounded review-batch row ids/hash",
|
|
722
|
+
"outputState": "messageDraftRecommendation"
|
|
1473
723
|
}
|
|
1474
724
|
],
|
|
1475
|
-
"
|
|
1476
|
-
|
|
725
|
+
"requiredCampaignState": [
|
|
726
|
+
"campaignId",
|
|
727
|
+
"campaignBrief",
|
|
728
|
+
"selectedLeadListId",
|
|
729
|
+
"workflowTableId"
|
|
730
|
+
],
|
|
1477
731
|
"allowedTools": [
|
|
1478
732
|
"get_subskill_prompt",
|
|
1479
733
|
"get_subskill_asset",
|
|
734
|
+
"get_campaign",
|
|
735
|
+
"get_rows_minimal",
|
|
1480
736
|
"AskUserQuestion",
|
|
1481
737
|
"request_user_input"
|
|
1482
738
|
],
|
|
1483
739
|
"toolRules": [
|
|
1484
|
-
"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.",
|
|
1485
741
|
"Do not use brief.md, lead-review.md, or lead-sample.json as required live state; those files are optional debug context only.",
|
|
1486
|
-
"
|
|
1487
|
-
"
|
|
1488
|
-
"The compact messageDraftRecommendation must return only templateRecommendation, tokenFillRules, renderedSample, concerns, status, basisToken, outputAt, outputHash, and error/retry detail. Its basis must include campaign revision or updatedAt, brief hash, selectedLeadListId, workflowTableId, bounded review-batch row ids/hash, filter choice, and filter/rubric basis when present.",
|
|
1489
|
-
"If current campaign state, selectedLeadListId, workflowTableId, or review-batch row ids/hash do not match the branch basis, classify the output stale or blocked; do not write message cells, enrich rows, attach sequence, or imply send readiness.",
|
|
1490
|
-
"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.",
|
|
1491
|
-
"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."
|
|
1492
744
|
],
|
|
1493
745
|
"doNotAllow": [
|
|
1494
746
|
"create_campaign",
|
|
747
|
+
"list_senders",
|
|
1495
748
|
"save_rubrics",
|
|
1496
749
|
"import_leads",
|
|
1497
750
|
"confirm_lead_list",
|
|
1498
751
|
"update_campaign",
|
|
1499
752
|
"queue_cells",
|
|
1500
753
|
"start_campaign",
|
|
1501
|
-
"generate_messages"
|
|
1502
|
-
"enrich_with_prospeo",
|
|
1503
|
-
"bulk_enrich_with_prospeo"
|
|
754
|
+
"generate_messages"
|
|
1504
755
|
],
|
|
1505
|
-
"watchRequired": false,
|
|
1506
756
|
"waitFor": [
|
|
1507
757
|
"message_validation_ready",
|
|
1508
758
|
"revise_rubric",
|
|
@@ -1516,728 +766,198 @@
|
|
|
1516
766
|
"revise_messaging": "message-generation",
|
|
1517
767
|
"confirm_with_user": "message-review",
|
|
1518
768
|
"auto_continue": "message-review"
|
|
1519
|
-
}
|
|
1520
|
-
"optionalRequiredArtifacts": [
|
|
1521
|
-
"lead-filter.md",
|
|
1522
|
-
"message-prep.md",
|
|
1523
|
-
"message-candidate-drafts.md"
|
|
1524
|
-
],
|
|
1525
|
-
"interruptOnly": true,
|
|
1526
|
-
"requiredCampaignState": [
|
|
1527
|
-
"campaignId",
|
|
1528
|
-
"campaignBrief",
|
|
1529
|
-
"selectedLeadListId",
|
|
1530
|
-
"workflowTableId"
|
|
1531
|
-
]
|
|
769
|
+
}
|
|
1532
770
|
},
|
|
1533
771
|
{
|
|
1534
772
|
"id": "message-review",
|
|
1535
|
-
"label": "Message review
|
|
1536
|
-
"normalFlow": true,
|
|
1537
|
-
"resumeOnly": false,
|
|
773
|
+
"label": "Message review",
|
|
1538
774
|
"onEnter": [
|
|
1539
775
|
{
|
|
1540
|
-
"action": "
|
|
776
|
+
"action": "render_message_review_from_state",
|
|
1541
777
|
"requiredState": [
|
|
1542
778
|
"campaignBrief",
|
|
1543
|
-
"selected source state",
|
|
1544
779
|
"selectedLeadListId",
|
|
1545
780
|
"workflowTableId",
|
|
1546
|
-
"
|
|
1547
|
-
"template recommendation with token fill rules and rendered sample"
|
|
1548
|
-
],
|
|
1549
|
-
"optionalDebugFiles": [
|
|
1550
|
-
"lead-filter.md",
|
|
1551
|
-
"message-validation.md",
|
|
1552
|
-
"message-prep.md",
|
|
1553
|
-
"message-candidate-drafts.md"
|
|
1554
|
-
]
|
|
1555
|
-
},
|
|
1556
|
-
{
|
|
1557
|
-
"action": "write_message_review",
|
|
1558
|
-
"artifact": "message-review.md",
|
|
1559
|
-
"requiredInlineMarker": "Status: message-review",
|
|
1560
|
-
"panels": [
|
|
1561
|
-
"subject",
|
|
1562
|
-
"sample prospect fill",
|
|
1563
|
-
"my take",
|
|
1564
|
-
"concern",
|
|
1565
|
-
"question",
|
|
1566
|
-
"recommendation"
|
|
781
|
+
"messageDraftRecommendation"
|
|
1567
782
|
],
|
|
1568
|
-
"
|
|
1569
|
-
"minimumVisibleMessageDetail": "filled_sample_message_only",
|
|
1570
|
-
"requiredArtifactLinks": ["message-review.md"],
|
|
1571
|
-
"artifactLinkTiming": "before_approval_question",
|
|
1572
|
-
"requiredFileLabels": [
|
|
783
|
+
"requiredVisibleLabels": [
|
|
1573
784
|
"Subject:",
|
|
1574
|
-
"Tokenized template:",
|
|
1575
785
|
"Sample prospect fill:",
|
|
1576
|
-
"Token fill basis:",
|
|
1577
|
-
"Rendered examples:",
|
|
1578
|
-
"Good token fill:",
|
|
1579
|
-
"Good omit:",
|
|
1580
|
-
"Bad token fill:",
|
|
1581
|
-
"Why bad:",
|
|
1582
|
-
"Fallback if missing:",
|
|
1583
|
-
"Token notes:",
|
|
1584
786
|
"My take:",
|
|
1585
|
-
"
|
|
1586
|
-
"Question: approve-message or revise-messaging?",
|
|
1587
|
-
"Recommendation:"
|
|
1588
|
-
]
|
|
1589
|
-
"requiredChatLabels": [
|
|
1590
|
-
"Status: message-review",
|
|
1591
|
-
"Subject:",
|
|
1592
|
-
"Sample prospect fill:",
|
|
1593
|
-
"My take:",
|
|
1594
|
-
"Concern:",
|
|
1595
|
-
"Question: approve-message or revise-messaging?",
|
|
1596
|
-
"Recommendation:"
|
|
1597
|
-
],
|
|
1598
|
-
"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.",
|
|
1599
|
-
"allowedRecommendations": ["approve-message", "revise-messaging"],
|
|
1600
|
-
"judgeAgainst": [
|
|
1601
|
-
"generate-messages rules",
|
|
1602
|
-
"gold-standard-* references",
|
|
1603
|
-
"opener strategy diversity",
|
|
1604
|
-
"raw sendable copy",
|
|
1605
|
-
"concrete enriched-row tokens",
|
|
1606
|
-
"no generic signal tokens",
|
|
1607
|
-
"no bracketed or deferred row instructions",
|
|
1608
|
-
"tokenized template with rendered examples",
|
|
1609
|
-
"tokenized template plus filled sample prospect",
|
|
1610
|
-
"good and bad token-fill examples",
|
|
1611
|
-
"per-token fallback rules for missing row data",
|
|
1612
|
-
"concrete fallback examples, not abstract fallback advice",
|
|
1613
|
-
"complete rendered subject plus body examples",
|
|
1614
|
-
"message-review hard-fail preflight",
|
|
1615
|
-
"A + B + C subject quality",
|
|
1616
|
-
"no generic subject lines",
|
|
1617
|
-
"product job before category nouns",
|
|
1618
|
-
"proof clarity",
|
|
1619
|
-
"CTA usefulness",
|
|
1620
|
-
"length and tightness",
|
|
1621
|
-
"campaign thesis fit"
|
|
1622
|
-
],
|
|
1623
|
-
"userFacing": true
|
|
1624
|
-
},
|
|
1625
|
-
{
|
|
1626
|
-
"action": "ask_message_review_choice",
|
|
1627
|
-
"choices": ["approve-message", "revise-messaging"],
|
|
1628
|
-
"questionPrerequisiteVisibleLabels": [
|
|
1629
|
-
"Status: message-review",
|
|
1630
|
-
"Subject:",
|
|
1631
|
-
"Tokenized template:",
|
|
1632
|
-
"Sample prospect fill:",
|
|
1633
|
-
"Token fill basis:",
|
|
1634
|
-
"My take:",
|
|
1635
|
-
"Suggested adjustment:",
|
|
1636
|
-
"Recommendation:"
|
|
1637
|
-
],
|
|
1638
|
-
"forbiddenWhenMissingVisibleMessage": true,
|
|
1639
|
-
"doNotOfferShowMessageChoice": true,
|
|
1640
|
-
"stopAfterQuestion": true
|
|
1641
|
-
},
|
|
1642
|
-
{
|
|
1643
|
-
"action": "write_message_review_decision",
|
|
1644
|
-
"artifact": "message-review-decision.md",
|
|
1645
|
-
"allowedChoices": ["approve-message", "revise-messaging"],
|
|
1646
|
-
"authorizesReviewBatchImportWhenApproved": true
|
|
1647
|
-
},
|
|
1648
|
-
{
|
|
1649
|
-
"action": "require_message_review_decision",
|
|
1650
|
-
"artifact": "message-review-decision.md",
|
|
1651
|
-
"requiredValue": "approve-message"
|
|
1652
|
-
},
|
|
1653
|
-
{
|
|
1654
|
-
"action": "sync_approved_message_set_to_campaign_brief",
|
|
1655
|
-
"tool": "update_campaign_brief",
|
|
1656
|
-
"requires": [
|
|
1657
|
-
"campaignId",
|
|
1658
|
-
"message-review-decision.md",
|
|
1659
|
-
"approved template recommendation",
|
|
1660
|
-
"saved filters when filters are enabled"
|
|
1661
|
-
],
|
|
1662
|
-
"when": "after_message_approved_before_product_messaging",
|
|
1663
|
-
"fields": [
|
|
1664
|
-
"campaignBrief with ## Approved Message Template containing {{...}} tokens, Token Fill Rules, Token Fill Examples"
|
|
1665
|
-
],
|
|
1666
|
-
"requiredBeforeImport": false,
|
|
1667
|
-
"onFailure": "stop_before_import_or_enrichment",
|
|
1668
|
-
"requiredBeforeCascade": true,
|
|
1669
|
-
"writesCampaignState": "campaignBrief.Approved Message Template"
|
|
1670
|
-
},
|
|
1671
|
-
{
|
|
1672
|
-
"action": "advance_watch_after_template_saved_before_cascade",
|
|
1673
|
-
"tool": "update_campaign",
|
|
1674
|
-
"requires": [
|
|
1675
|
-
"campaignId",
|
|
1676
|
-
"campaignBrief.Approved Message Template",
|
|
1677
|
-
"leadScoringRubrics"
|
|
1678
|
-
],
|
|
1679
|
-
"requiredValues": {
|
|
1680
|
-
"currentStep": "apply-icp-rubric",
|
|
1681
|
-
"enableICPFilters": true,
|
|
1682
|
-
"watchNarration.stage": "fit-message",
|
|
1683
|
-
"watchNarration.headline": "Template saved",
|
|
1684
|
-
"watchNarration.workerStatuses.leadFitBuilder": "ready",
|
|
1685
|
-
"watchNarration.workerStatuses.messageDraftBuilder": "ready"
|
|
1686
|
-
},
|
|
1687
|
-
"when": "immediately_after_update_campaign_brief_succeeds_before_get_rows_or_queue_cells",
|
|
1688
|
-
"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."
|
|
1689
|
-
},
|
|
1690
|
-
{
|
|
1691
|
-
"tool": "get_rows_minimal",
|
|
1692
|
-
"purpose": "read_bounded_review_batch_cell_ids_after_message_approval",
|
|
1693
|
-
"requiredBeforeCascade": true
|
|
1694
|
-
},
|
|
1695
|
-
{
|
|
1696
|
-
"tool": "queue_cells",
|
|
1697
|
-
"requiredValues": {
|
|
1698
|
-
"tableId": "workflowTableId",
|
|
1699
|
-
"cellSource": "bounded_review_batch_enrichCellIds",
|
|
1700
|
-
"statusFilter": ["pending", "error", "dependency_blocked"]
|
|
1701
|
-
},
|
|
1702
|
-
"purpose": "queue_bounded_review_batch_enrichment_after_approved_template",
|
|
1703
|
-
"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."
|
|
1704
|
-
},
|
|
1705
|
-
{
|
|
1706
|
-
"tool": "wait_for_rubric_results",
|
|
1707
|
-
"requiredValues": {
|
|
1708
|
-
"includeRows": false,
|
|
1709
|
-
"minPassedCount": 2,
|
|
1710
|
-
"targetCount": "bounded review batch count"
|
|
1711
|
-
},
|
|
1712
|
-
"purpose": "wait_for_bounded_filter_run_after_message_approval_before_messages_step",
|
|
1713
|
-
"readVia": "stats_only_tool_result",
|
|
1714
|
-
"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."
|
|
1715
|
-
},
|
|
1716
|
-
{
|
|
1717
|
-
"action": "advance_watch_to_messaging_after_filter_passes",
|
|
1718
|
-
"tool": "update_campaign",
|
|
1719
|
-
"requires": [
|
|
1720
|
-
"campaignId",
|
|
1721
|
-
"message-review-decision.md",
|
|
1722
|
-
"campaignBrief.Approved Message Template",
|
|
1723
|
-
"bounded filter run with usable passing rows"
|
|
1724
|
-
],
|
|
1725
|
-
"requiredValues": {
|
|
1726
|
-
"currentStep": "auto-execute-messaging",
|
|
1727
|
-
"enableICPFilters": true,
|
|
1728
|
-
"watchNarration.stage": "review-ready"
|
|
1729
|
-
},
|
|
1730
|
-
"when": "after_update_campaign_brief_succeeds_and_bounded_filter_run_has_passing_rows",
|
|
1731
|
-
"requiredBeforeGenerateMessageCascade": true,
|
|
1732
|
-
"writesCampaignState": "currentStep:auto-execute-messaging"
|
|
1733
|
-
}
|
|
1734
|
-
],
|
|
1735
|
-
"requiredArtifacts": [
|
|
1736
|
-
"brief.md",
|
|
1737
|
-
"lead-review.md",
|
|
1738
|
-
"lead-sample.json",
|
|
1739
|
-
"message-validation.md"
|
|
1740
|
-
],
|
|
1741
|
-
"optionalRequiredArtifacts": ["lead-filter.md"],
|
|
1742
|
-
"producesArtifacts": ["message-review.md", "message-review-decision.md"],
|
|
1743
|
-
"allowedTools": [
|
|
1744
|
-
"AskUserQuestion",
|
|
1745
|
-
"request_user_input",
|
|
1746
|
-
"get_subskill_prompt",
|
|
1747
|
-
"update_campaign_brief",
|
|
1748
|
-
"update_campaign",
|
|
1749
|
-
"get_rows_minimal",
|
|
1750
|
-
"queue_cells",
|
|
1751
|
-
"wait_for_rubric_results"
|
|
1752
|
-
],
|
|
1753
|
-
"doNotAllow": [
|
|
1754
|
-
"create_campaign",
|
|
1755
|
-
"save_rubrics",
|
|
1756
|
-
"import_leads",
|
|
1757
|
-
"confirm_lead_list",
|
|
1758
|
-
"start_campaign",
|
|
1759
|
-
"enrich_with_prospeo",
|
|
1760
|
-
"bulk_enrich_with_prospeo"
|
|
1761
|
-
],
|
|
1762
|
-
"watchRequired": false,
|
|
1763
|
-
"waitFor": ["message_approved", "revise_messaging"],
|
|
1764
|
-
"transitions": {
|
|
1765
|
-
"message_approved": "auto-execute-messaging",
|
|
1766
|
-
"revise_messaging": "message-generation"
|
|
1767
|
-
},
|
|
1768
|
-
"interruptOnly": true,
|
|
1769
|
-
"requiredCampaignState": ["campaignId", "workflowTableId"]
|
|
1770
|
-
},
|
|
1771
|
-
{
|
|
1772
|
-
"id": "approval-packet",
|
|
1773
|
-
"label": "Approval packet",
|
|
1774
|
-
"normalFlow": false,
|
|
1775
|
-
"resumeOnly": true,
|
|
1776
|
-
"onEnter": [
|
|
1777
|
-
{
|
|
1778
|
-
"action": "read_draft_artifacts",
|
|
1779
|
-
"requiredFiles": [
|
|
1780
|
-
"brief.md",
|
|
1781
|
-
"lead-review.md",
|
|
1782
|
-
"lead-sample.json",
|
|
1783
|
-
"lead-filter.md",
|
|
1784
|
-
"message-validation.md",
|
|
1785
|
-
"message-review.md",
|
|
1786
|
-
"message-review-decision.md"
|
|
1787
|
-
],
|
|
1788
|
-
"optionalFiles": ["rubric.json"]
|
|
1789
|
-
},
|
|
1790
|
-
{
|
|
1791
|
-
"action": "require_message_review_decision",
|
|
1792
|
-
"artifact": "message-review-decision.md",
|
|
1793
|
-
"requiredValue": "approve-message",
|
|
1794
|
-
"doesNotAuthorizeMint": true
|
|
1795
|
-
},
|
|
1796
|
-
{
|
|
1797
|
-
"action": "write_approval_packet",
|
|
1798
|
-
"artifact": "approval-packet.md",
|
|
1799
|
-
"requiredInlineMarker": "Status: approval-packet",
|
|
1800
|
-
"mustRenderInlineBeforeCommitGate": true,
|
|
1801
|
-
"panels": [
|
|
1802
|
-
"campaign direction",
|
|
1803
|
-
"lead source",
|
|
1804
|
-
"filter",
|
|
1805
|
-
"sample message",
|
|
1806
|
-
"what approval creates"
|
|
1807
|
-
],
|
|
1808
|
-
"minimumVisibleDetail": "slim_final_approval_summary",
|
|
1809
|
-
"requiredArtifactLinks": ["approval-packet.md"],
|
|
1810
|
-
"artifactLinkTiming": "before_commit_gate_question",
|
|
1811
|
-
"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.",
|
|
1812
|
-
"userFacing": true,
|
|
1813
|
-
"doNotUseWords": ["anchor", "validation anchor", "lane"]
|
|
1814
|
-
},
|
|
1815
|
-
{
|
|
1816
|
-
"action": "optional_customer_roleplay",
|
|
1817
|
-
"artifact": "customer-roleplay.md",
|
|
1818
|
-
"advisoryOnly": true,
|
|
1819
|
-
"cannotAuthorizeMint": true
|
|
1820
|
-
}
|
|
1821
|
-
],
|
|
1822
|
-
"requiredArtifacts": [
|
|
1823
|
-
"brief.md",
|
|
1824
|
-
"lead-review.md",
|
|
1825
|
-
"lead-sample.json",
|
|
1826
|
-
"lead-filter.md",
|
|
1827
|
-
"message-validation.md",
|
|
1828
|
-
"message-review.md",
|
|
1829
|
-
"message-review-decision.md"
|
|
1830
|
-
],
|
|
1831
|
-
"producesArtifacts": ["approval-packet.md"],
|
|
1832
|
-
"optionalProducesArtifacts": ["customer-roleplay.md"],
|
|
1833
|
-
"allowedTools": [
|
|
1834
|
-
"AskUserQuestion",
|
|
1835
|
-
"request_user_input",
|
|
1836
|
-
"get_subskill_prompt"
|
|
1837
|
-
],
|
|
1838
|
-
"doNotAllow": [
|
|
1839
|
-
"create_campaign",
|
|
1840
|
-
"save_rubrics",
|
|
1841
|
-
"import_leads",
|
|
1842
|
-
"confirm_lead_list",
|
|
1843
|
-
"update_campaign",
|
|
1844
|
-
"queue_cells",
|
|
1845
|
-
"start_campaign",
|
|
1846
|
-
"enrich_with_prospeo",
|
|
1847
|
-
"bulk_enrich_with_prospeo"
|
|
1848
|
-
],
|
|
1849
|
-
"watchRequired": false,
|
|
1850
|
-
"waitFor": "approval_packet_ready",
|
|
1851
|
-
"transitions": {},
|
|
1852
|
-
"optionalRequiredArtifacts": ["lead-source-intake.json"],
|
|
1853
|
-
"deprecated": true,
|
|
1854
|
-
"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."
|
|
1855
|
-
},
|
|
1856
|
-
{
|
|
1857
|
-
"id": "validate-artifacts",
|
|
1858
|
-
"label": "Validate chained artifacts",
|
|
1859
|
-
"onEnter": [
|
|
1860
|
-
{
|
|
1861
|
-
"action": "read_draft_artifacts",
|
|
1862
|
-
"requiredFiles": [
|
|
1863
|
-
"brief.md",
|
|
1864
|
-
"lead-review.md",
|
|
1865
|
-
"lead-sample.json",
|
|
1866
|
-
"lead-filter.md",
|
|
1867
|
-
"message-validation.md"
|
|
1868
|
-
],
|
|
1869
|
-
"optionalFiles": ["rubric.json"]
|
|
1870
|
-
},
|
|
1871
|
-
{
|
|
1872
|
-
"action": "validate_anchors",
|
|
1873
|
-
"blockOnEmpty": true
|
|
1874
|
-
},
|
|
1875
|
-
{
|
|
1876
|
-
"action": "require_message_review_decision",
|
|
1877
|
-
"artifact": "message-review-decision.md",
|
|
1878
|
-
"requiredValue": "approve-message",
|
|
1879
|
-
"doesNotAuthorizeMint": true
|
|
1880
|
-
}
|
|
1881
|
-
],
|
|
1882
|
-
"allowedTools": ["AskUserQuestion", "request_user_input"],
|
|
1883
|
-
"watchRequired": false,
|
|
1884
|
-
"waitFor": "artifacts_validated",
|
|
1885
|
-
"transitions": {},
|
|
1886
|
-
"optionalRequiredArtifacts": ["lead-source-intake.json"],
|
|
1887
|
-
"deprecated": true,
|
|
1888
|
-
"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.",
|
|
1889
|
-
"resumeOnly": true,
|
|
1890
|
-
"normalFlow": false
|
|
1891
|
-
},
|
|
1892
|
-
{
|
|
1893
|
-
"id": "commit-gate",
|
|
1894
|
-
"label": "Commit gate",
|
|
1895
|
-
"onEnter": [
|
|
1896
|
-
{
|
|
1897
|
-
"action": "require_message_review_decision",
|
|
1898
|
-
"artifact": "message-review-decision.md",
|
|
1899
|
-
"requiredValue": "approve-message",
|
|
1900
|
-
"doesNotAuthorizeMint": true
|
|
1901
|
-
},
|
|
1902
|
-
{
|
|
1903
|
-
"action": "show_approval_packet",
|
|
1904
|
-
"requiredInlineMarker": "Status: approval-packet",
|
|
1905
|
-
"sameTurnAsCommitQuestion": true,
|
|
1906
|
-
"panels": [
|
|
1907
|
-
"campaign direction",
|
|
1908
|
-
"lead source",
|
|
1909
|
-
"filter",
|
|
1910
|
-
"sample message",
|
|
1911
|
-
"what approval creates"
|
|
1912
|
-
],
|
|
1913
|
-
"requiredArtifactLinks": ["approval-packet.md"],
|
|
1914
|
-
"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.",
|
|
1915
|
-
"artifactLinkTiming": "same_turn_before_commit_question"
|
|
1916
|
-
},
|
|
1917
|
-
{
|
|
1918
|
-
"action": "ask_commit_choice",
|
|
1919
|
-
"choices": [
|
|
1920
|
-
"approve",
|
|
1921
|
-
"revise-brief",
|
|
1922
|
-
"revise-leads",
|
|
1923
|
-
"revise-rubric",
|
|
1924
|
-
"revise-messaging",
|
|
1925
|
-
"abort"
|
|
1926
|
-
]
|
|
1927
|
-
},
|
|
1928
|
-
{
|
|
1929
|
-
"action": "write_commit_gate_decision",
|
|
1930
|
-
"artifact": "commit-gate-decision.md",
|
|
1931
|
-
"allowedChoices": [
|
|
1932
|
-
"approve",
|
|
1933
|
-
"revise-brief",
|
|
1934
|
-
"revise-leads",
|
|
1935
|
-
"revise-rubric",
|
|
1936
|
-
"revise-messaging",
|
|
1937
|
-
"abort"
|
|
1938
|
-
],
|
|
1939
|
-
"onlyApproveAuthorizesMint": true
|
|
1940
|
-
}
|
|
1941
|
-
],
|
|
1942
|
-
"allowedTools": ["AskUserQuestion", "request_user_input"],
|
|
1943
|
-
"watchRequired": false,
|
|
1944
|
-
"waitFor": [
|
|
1945
|
-
"user_approved",
|
|
1946
|
-
"user_revise_brief",
|
|
1947
|
-
"user_revise_leads",
|
|
1948
|
-
"user_revise_rubric",
|
|
1949
|
-
"user_revise_messaging",
|
|
1950
|
-
"user_abort"
|
|
1951
|
-
],
|
|
1952
|
-
"transitions": {},
|
|
1953
|
-
"optionalRequiredArtifacts": ["lead-source-intake.json"],
|
|
1954
|
-
"deprecated": true,
|
|
1955
|
-
"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.",
|
|
1956
|
-
"resumeOnly": true,
|
|
1957
|
-
"normalFlow": false
|
|
1958
|
-
},
|
|
1959
|
-
{
|
|
1960
|
-
"id": "atomic-mint",
|
|
1961
|
-
"label": "Atomic mint",
|
|
1962
|
-
"currentStepValue": "auto-execute-leads",
|
|
1963
|
-
"onEnter": [
|
|
1964
|
-
{
|
|
1965
|
-
"tool": "bootstrap_create_campaign",
|
|
1966
|
-
"requiredValues": {
|
|
1967
|
-
"flowVersion": "v2"
|
|
1968
|
-
}
|
|
1969
|
-
},
|
|
1970
|
-
{
|
|
1971
|
-
"tool": "create_campaign",
|
|
1972
|
-
"mode": "create_new_or_resume_draft_shell",
|
|
1973
|
-
"shellArtifact": "campaign-shell.json",
|
|
1974
|
-
"requiredFields": ["campaignBrief", "currentStep"],
|
|
1975
|
-
"requiredValues": {
|
|
1976
|
-
"currentStep": "auto-execute-leads"
|
|
1977
|
-
},
|
|
1978
|
-
"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.",
|
|
1979
|
-
"requiredCampaignBriefSections": [
|
|
1980
|
-
"Approved Message Template",
|
|
1981
|
-
"Token Fill Rules",
|
|
1982
|
-
"Token Fill Examples"
|
|
1983
|
-
],
|
|
1984
|
-
"preserveTokenGuidanceFromArtifacts": [
|
|
1985
|
-
"message-review.md",
|
|
1986
|
-
"message-validation.md"
|
|
1987
|
-
],
|
|
1988
|
-
"requiredTokenGuidanceLabels": [
|
|
1989
|
-
"Good token fill:",
|
|
1990
|
-
"Good omit:",
|
|
1991
|
-
"Bad token fill:",
|
|
1992
|
-
"Why bad:",
|
|
1993
|
-
"Fallback if missing:",
|
|
1994
|
-
"Token fill basis:"
|
|
1995
|
-
],
|
|
1996
|
-
"capture": ["campaignId", "watchUrl"],
|
|
1997
|
-
"onMissingWatchUrl": "recoverable_failure_abort_before_rubric_save"
|
|
1998
|
-
},
|
|
1999
|
-
{
|
|
2000
|
-
"tool": "update_campaign",
|
|
2001
|
-
"when": "campaign-shell.json exists",
|
|
2002
|
-
"requiredFields": ["campaignId", "campaignBrief", "currentStep"],
|
|
2003
|
-
"requiredValues": {
|
|
2004
|
-
"currentStep": "auto-execute-leads"
|
|
2005
|
-
},
|
|
2006
|
-
"fields": ["campaignBrief", "leadSourceType", "leadSourceProvider"],
|
|
2007
|
-
"skipWhen": "create_campaign minted a new campaign with the final approved brief and currentStep already set"
|
|
2008
|
-
},
|
|
2009
|
-
{
|
|
2010
|
-
"tool": "save_rubrics",
|
|
2011
|
-
"requiredFields": ["rubric"],
|
|
2012
|
-
"idempotentWhenAlreadySavedToDraftShell": true,
|
|
2013
|
-
"onFailure": "rollback_or_recoverable_stop"
|
|
2014
|
-
},
|
|
2015
|
-
{
|
|
2016
|
-
"action": "flip_brief_status_to_committed"
|
|
2017
|
-
},
|
|
2018
|
-
{
|
|
2019
|
-
"action": "move_draft_dir_to_committed"
|
|
2020
|
-
},
|
|
2021
|
-
{
|
|
2022
|
-
"action": "surface_watch_link",
|
|
2023
|
-
"requires": ["create_campaign_succeeded", "save_rubrics_succeeded"],
|
|
2024
|
-
"reference": "references/watch-link-handoff.md",
|
|
2025
|
-
"requiredVisibleContent": [
|
|
2026
|
-
"Campaign created",
|
|
2027
|
-
"approved brief",
|
|
2028
|
-
"Open this to watch",
|
|
2029
|
-
"Find Leads",
|
|
2030
|
-
"rubric scoring",
|
|
2031
|
-
"messaging populate live",
|
|
2032
|
-
"Watch link:"
|
|
2033
|
-
],
|
|
2034
|
-
"watchUrlSource": "create_campaign.watchUrl"
|
|
2035
|
-
}
|
|
2036
|
-
],
|
|
2037
|
-
"allowedTools": [
|
|
2038
|
-
"bootstrap_create_campaign",
|
|
2039
|
-
"create_campaign",
|
|
2040
|
-
"update_campaign",
|
|
2041
|
-
"save_rubrics",
|
|
2042
|
-
"AskUserQuestion",
|
|
2043
|
-
"request_user_input"
|
|
2044
|
-
],
|
|
2045
|
-
"doNotAllow": ["import_leads"],
|
|
2046
|
-
"watchRequired": true,
|
|
2047
|
-
"waitFor": "autonomous_tail_started",
|
|
2048
|
-
"transitions": {},
|
|
2049
|
-
"deprecated": true,
|
|
2050
|
-
"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.",
|
|
2051
|
-
"resumeOnly": true,
|
|
2052
|
-
"normalFlow": false
|
|
2053
|
-
},
|
|
2054
|
-
{
|
|
2055
|
-
"id": "autonomous-tail-handoff",
|
|
2056
|
-
"label": "Handoff to autonomous tail (Plan 85-02)",
|
|
2057
|
-
"onEnter": [
|
|
2058
|
-
{
|
|
2059
|
-
"action": "resume_watch_link"
|
|
787
|
+
"Concern:",
|
|
788
|
+
"Question: approve-message or revise-messaging?",
|
|
789
|
+
"Recommendation:"
|
|
790
|
+
]
|
|
2060
791
|
},
|
|
2061
792
|
{
|
|
2062
|
-
"action": "
|
|
2063
|
-
"
|
|
2064
|
-
"
|
|
2065
|
-
|
|
2066
|
-
"
|
|
2067
|
-
|
|
2068
|
-
},
|
|
2069
|
-
"loadOnce": true
|
|
793
|
+
"action": "ask_message_review_choice",
|
|
794
|
+
"uses": "request_user_input",
|
|
795
|
+
"choices": [
|
|
796
|
+
"approve-message",
|
|
797
|
+
"revise-messaging"
|
|
798
|
+
]
|
|
2070
799
|
},
|
|
2071
800
|
{
|
|
2072
|
-
"action": "
|
|
2073
|
-
"
|
|
801
|
+
"action": "sync_approved_message_set_to_campaign_brief",
|
|
802
|
+
"tool": "update_campaign_brief",
|
|
803
|
+
"when": "after approve-message",
|
|
804
|
+
"requiredFields": [
|
|
805
|
+
"campaignId",
|
|
806
|
+
"approvedMessageTemplate",
|
|
807
|
+
"Token Fill Rules",
|
|
808
|
+
"Token Fill Examples"
|
|
809
|
+
],
|
|
810
|
+
"writesCampaignState": "approvedMessageTemplate"
|
|
2074
811
|
}
|
|
2075
812
|
],
|
|
813
|
+
"requiredCampaignState": [
|
|
814
|
+
"campaignId",
|
|
815
|
+
"workflowTableId",
|
|
816
|
+
"messageDraftRecommendation"
|
|
817
|
+
],
|
|
2076
818
|
"allowedTools": [
|
|
2077
|
-
"get_subskill_asset",
|
|
2078
819
|
"AskUserQuestion",
|
|
2079
|
-
"request_user_input"
|
|
820
|
+
"request_user_input",
|
|
821
|
+
"get_subskill_asset",
|
|
822
|
+
"update_campaign_brief",
|
|
823
|
+
"update_campaign",
|
|
824
|
+
"get_rows_minimal",
|
|
825
|
+
"queue_cells",
|
|
826
|
+
"wait_for_rubric_results"
|
|
827
|
+
],
|
|
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"
|
|
2080
839
|
],
|
|
2081
840
|
"transitions": {
|
|
2082
|
-
"
|
|
841
|
+
"message_approved": "validate-sample",
|
|
842
|
+
"revise_messaging": "message-generation"
|
|
2083
843
|
}
|
|
2084
844
|
},
|
|
2085
845
|
{
|
|
2086
846
|
"id": "validate-sample",
|
|
2087
|
-
"label": "
|
|
847
|
+
"label": "Validate bounded review batch",
|
|
2088
848
|
"currentStepValue": "validate-sample",
|
|
2089
|
-
"normalFlow": false,
|
|
2090
|
-
"resumeOnly": true,
|
|
2091
|
-
"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.",
|
|
2092
849
|
"reference": "references/sample-validation-loop.md",
|
|
2093
|
-
"counter": {
|
|
2094
|
-
"name": "revisionRound",
|
|
2095
|
-
"initialValue": 0,
|
|
2096
|
-
"persistAcrossResume": true,
|
|
2097
|
-
"resetOnResume": false,
|
|
2098
|
-
"capFromConfig": "sample.maxRevisionRounds"
|
|
2099
|
-
},
|
|
2100
850
|
"onEnter": [
|
|
2101
|
-
{
|
|
2102
|
-
"action": "resolve_messages_mode",
|
|
2103
|
-
"branches": {
|
|
2104
|
-
"use-template": "Use the approved template/token rules already synced into CampaignOffer.campaignBrief.",
|
|
2105
|
-
"ai-generated": "Use the explicit AI-generated product path and cancel or ignore any background template draft."
|
|
2106
|
-
},
|
|
2107
|
-
"rule": "AI Generated mode must not read, apply, or be overwritten by the background Message Draft Builder template."
|
|
2108
|
-
},
|
|
2109
|
-
{
|
|
2110
|
-
"action": "watch_mode_orient"
|
|
2111
|
-
},
|
|
2112
851
|
{
|
|
2113
852
|
"tool": "queue_cells",
|
|
2114
|
-
"
|
|
2115
|
-
"
|
|
2116
|
-
|
|
2117
|
-
"
|
|
2118
|
-
"
|
|
853
|
+
"purpose": "queue ICP/enrichment cells for the bounded review batch only",
|
|
854
|
+
"requiredFields": [
|
|
855
|
+
"workflowTableId",
|
|
856
|
+
"reviewBatchRowIds",
|
|
857
|
+
"cellTypes"
|
|
2119
858
|
],
|
|
2120
|
-
"
|
|
859
|
+
"targetCountSource": "reviewBatchRowIds.length"
|
|
2121
860
|
},
|
|
2122
861
|
{
|
|
2123
862
|
"tool": "wait_for_campaign_table_ready",
|
|
2124
|
-
"purpose": "
|
|
863
|
+
"purpose": "wait_for_review_batch_scoring_cells"
|
|
2125
864
|
},
|
|
2126
865
|
{
|
|
2127
866
|
"tool": "get_rows_minimal",
|
|
2128
|
-
"
|
|
2129
|
-
|
|
2130
|
-
|
|
867
|
+
"requiredValues": {
|
|
868
|
+
"includeRows": false
|
|
869
|
+
},
|
|
870
|
+
"purpose": "read compact row status only"
|
|
2131
871
|
},
|
|
2132
872
|
{
|
|
2133
873
|
"tool": "wait_for_rubric_results",
|
|
2134
|
-
"requiredFields": [
|
|
2135
|
-
|
|
2136
|
-
|
|
874
|
+
"requiredFields": [
|
|
875
|
+
"workflowTableId",
|
|
876
|
+
"targetCount",
|
|
877
|
+
"minPassedCount"
|
|
878
|
+
],
|
|
2137
879
|
"requiredValues": {
|
|
2138
880
|
"includeRows": false,
|
|
2139
881
|
"minPassedCount": 1
|
|
2140
882
|
},
|
|
2141
|
-
"
|
|
2142
|
-
"readVia": "stats_only_tool_result"
|
|
2143
|
-
"extractFields": [
|
|
2144
|
-
"ready",
|
|
2145
|
-
"partial",
|
|
2146
|
-
"reason",
|
|
2147
|
-
"passRate.completed",
|
|
2148
|
-
"passRate.passed",
|
|
2149
|
-
"passRate.minPassedCount",
|
|
2150
|
-
"stats"
|
|
2151
|
-
],
|
|
2152
|
-
"doNotRetain": "rows_payload",
|
|
2153
|
-
"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"
|
|
2154
885
|
},
|
|
2155
886
|
{
|
|
2156
887
|
"action": "handle_partial_or_timeout_sample",
|
|
2157
|
-
"when": "wait_for_rubric_results.ready_false_or_reason_timeout",
|
|
2158
|
-
"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.",
|
|
2159
888
|
"customerStatus": "sample-needs-revision",
|
|
2160
|
-
"
|
|
2161
|
-
"passRate.completed",
|
|
2162
|
-
"passRate.passed",
|
|
2163
|
-
"passRate.pending",
|
|
2164
|
-
"passRate.percent",
|
|
2165
|
-
"stats.messagesCount"
|
|
2166
|
-
]
|
|
2167
|
-
},
|
|
2168
|
-
{
|
|
2169
|
-
"action": "compute_projected_pass",
|
|
2170
|
-
"formula": "round(passInSample / sampleSize * importLimit)",
|
|
2171
|
-
"floorFromConfig": "sample.minProjectedPass"
|
|
2172
|
-
},
|
|
2173
|
-
{
|
|
2174
|
-
"action": "diagnose_brief_vs_list",
|
|
2175
|
-
"onBrief": "update_campaign_brief_and_rerun",
|
|
2176
|
-
"onList": "escalate",
|
|
2177
|
-
"onUnknown": "escalate"
|
|
2178
|
-
},
|
|
2179
|
-
{
|
|
2180
|
-
"action": "increment_revision_round",
|
|
2181
|
-
"capTripEvent": "escalation_triggered"
|
|
889
|
+
"rule": "Do not repeat waits indefinitely; surface partial status and route to revision."
|
|
2182
890
|
}
|
|
2183
891
|
],
|
|
892
|
+
"requiredCampaignState": [
|
|
893
|
+
"campaignId",
|
|
894
|
+
"workflowTableId",
|
|
895
|
+
"approvedMessageTemplate"
|
|
896
|
+
],
|
|
2184
897
|
"allowedTools": [
|
|
2185
898
|
"get_subskill_asset",
|
|
2186
899
|
"queue_cells",
|
|
2187
900
|
"wait_for_campaign_table_ready",
|
|
2188
901
|
"get_rows_minimal",
|
|
2189
902
|
"wait_for_rubric_results",
|
|
2190
|
-
"update_campaign_brief",
|
|
2191
903
|
"update_campaign",
|
|
2192
904
|
"AskUserQuestion",
|
|
2193
905
|
"request_user_input"
|
|
2194
906
|
],
|
|
2195
907
|
"doNotAllow": [
|
|
2196
908
|
"import_leads",
|
|
909
|
+
"list_senders",
|
|
2197
910
|
"start_campaign",
|
|
2198
911
|
"enrich_with_prospeo",
|
|
2199
912
|
"bulk_enrich_with_prospeo",
|
|
2200
913
|
"check_rubric"
|
|
2201
914
|
],
|
|
2202
915
|
"hardRules": [
|
|
2203
|
-
"list_problem_never_triggers_autonomous_update_campaign_brief",
|
|
2204
|
-
"revision_round_persists_across_resume",
|
|
2205
916
|
"wait_for_rubric_results_never_retain_rows_payload_in_tail_context",
|
|
2206
917
|
"wait_for_rubric_results_targetCount_always_explicit",
|
|
2207
|
-
"first_passing_row_unblocks_generate_message_observation",
|
|
2208
918
|
"timeout_never_repeats_without_customer_handoff",
|
|
2209
|
-
"timeout_or_underfloor_sample_never_advances_to_settings"
|
|
2210
|
-
|
|
2211
|
-
|
|
919
|
+
"timeout_or_underfloor_sample_never_advances_to_settings"
|
|
920
|
+
],
|
|
921
|
+
"waitFor": [
|
|
922
|
+
"sample_validated",
|
|
923
|
+
"sample_revision_required"
|
|
2212
924
|
],
|
|
2213
|
-
"watchRequired": true,
|
|
2214
|
-
"waitFor": ["sample_validated", "sample_revision_required"],
|
|
2215
925
|
"transitions": {
|
|
2216
926
|
"sample_validated": "auto-execute-messaging",
|
|
2217
927
|
"sample_revision_required": "lead-review",
|
|
2218
928
|
"revise_leads": "find-leads",
|
|
2219
929
|
"revise_rubric": "filter-rubric",
|
|
2220
930
|
"escalation_triggered": "escalation"
|
|
2221
|
-
}
|
|
2222
|
-
"requiredCampaignState": [
|
|
2223
|
-
"campaignId",
|
|
2224
|
-
"workflowTableId",
|
|
2225
|
-
"leadScoringRubrics",
|
|
2226
|
-
"approvedMessageTemplate"
|
|
2227
|
-
]
|
|
931
|
+
}
|
|
2228
932
|
},
|
|
2229
933
|
{
|
|
2230
934
|
"id": "auto-execute-messaging",
|
|
2231
|
-
"label": "
|
|
935
|
+
"label": "Generate review-batch messages",
|
|
2232
936
|
"currentStepValue": "auto-execute-messaging",
|
|
2233
937
|
"references": [
|
|
2234
938
|
"references/parallel-critique-protocol.md",
|
|
2235
939
|
"references/thomas-variant-selection.md",
|
|
2236
|
-
"references/thomas-revision-filters.md"
|
|
940
|
+
"references/thomas-revision-filters.md",
|
|
941
|
+
"references/step-15-re-cascade.md"
|
|
2237
942
|
],
|
|
2238
943
|
"onEnter": [
|
|
2239
944
|
{
|
|
2240
|
-
"
|
|
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"
|
|
2241
961
|
},
|
|
2242
962
|
{
|
|
2243
963
|
"action": "optional_critique_pass",
|
|
@@ -2249,7 +969,6 @@
|
|
|
2249
969
|
"perCriticTimeoutFromConfig": "messaging.critique.perCriticTimeoutSeconds",
|
|
2250
970
|
"totalTimeoutFromConfig": "messaging.critique.totalTimeoutSeconds",
|
|
2251
971
|
"criticsFromConfig": "messaging.critique.critics",
|
|
2252
|
-
"synthesisModelFromConfig": "messaging.critique.synthesis.model",
|
|
2253
972
|
"enforceFinalizerPassFromConfig": "messaging.critique.synthesis.enforceFinalizerPass",
|
|
2254
973
|
"rejectOnFakeProofFromConfig": "messaging.critique.rejectOnFakeProof",
|
|
2255
974
|
"rejectOnUnsupportedTokenFromConfig": "messaging.critique.rejectOnUnsupportedToken",
|
|
@@ -2268,46 +987,13 @@
|
|
|
2268
987
|
"onOpusBudgetTrip": "halt_opus_continue_non_opus",
|
|
2269
988
|
"onOpusTokenContractViolation": "fallback_to_non_opus_rewrite"
|
|
2270
989
|
},
|
|
2271
|
-
{
|
|
2272
|
-
"action": "enforce_token_contract",
|
|
2273
|
-
"modeFromConfig": "messaging.tokenContract"
|
|
2274
|
-
},
|
|
2275
|
-
{
|
|
2276
|
-
"action": "verify_campaign_brief_template_mode",
|
|
2277
|
-
"requiredSection": "Approved Message Template",
|
|
2278
|
-
"requiredPattern": "{{...}}",
|
|
2279
|
-
"onFailure": "runtime_failure_before_messaging",
|
|
2280
|
-
"repairBoundary": "before_import_only",
|
|
2281
|
-
"purpose": "ensure Generate Message uses the approved template instead of full-generation mode"
|
|
2282
|
-
},
|
|
2283
|
-
{
|
|
2284
|
-
"tool": "get_rows_minimal",
|
|
2285
|
-
"purpose": "confirm_passing_rows_have_completed_generate_message_cells"
|
|
2286
|
-
},
|
|
2287
|
-
{
|
|
2288
|
-
"tool": "queue_cells",
|
|
2289
|
-
"cellSource": "pending_generate_message_cells_for_passing_rows_using_approved_campaign_brief_template",
|
|
2290
|
-
"when": "any passing row has pending or empty Generate Message cell",
|
|
2291
|
-
"batchSize": 100
|
|
2292
|
-
},
|
|
2293
|
-
{
|
|
2294
|
-
"tool": "wait_for_campaign_table_ready",
|
|
2295
|
-
"purpose": "wait_for_generate_message_cells_to_complete"
|
|
2296
|
-
},
|
|
2297
|
-
{
|
|
2298
|
-
"action": "observe_generate_message_results",
|
|
2299
|
-
"reference": "references/step-15-re-cascade.md",
|
|
2300
|
-
"trigger": "rows_flipped_pending_to_passed_after_first_generate_messages",
|
|
2301
|
-
"note": "Generate Message is produced by the workflow-table cascade. Do not call direct generate_messages in the autonomous tail."
|
|
2302
|
-
},
|
|
2303
990
|
{
|
|
2304
991
|
"tool": "update_campaign",
|
|
2305
|
-
"requiredFields": ["campaignId", "currentStep", "watchNarration"],
|
|
2306
992
|
"requiredValues": {
|
|
2307
993
|
"currentStep": "awaiting-user-greenlight",
|
|
2308
994
|
"watchNarration.stage": "review-ready"
|
|
2309
995
|
},
|
|
2310
|
-
"watchNarrationRule": "Say
|
|
996
|
+
"watchNarrationRule": "Say what just happened, that review-batch messages are ready, and that the next action is Settings/sender review."
|
|
2311
997
|
}
|
|
2312
998
|
],
|
|
2313
999
|
"allowedTools": [
|
|
@@ -2315,25 +1001,28 @@
|
|
|
2315
1001
|
"get_rows_minimal",
|
|
2316
1002
|
"queue_cells",
|
|
2317
1003
|
"wait_for_campaign_table_ready",
|
|
2318
|
-
"update_campaign_brief",
|
|
2319
1004
|
"update_campaign",
|
|
2320
1005
|
"AskUserQuestion",
|
|
2321
1006
|
"request_user_input"
|
|
2322
1007
|
],
|
|
2323
|
-
"doNotAllow": [
|
|
1008
|
+
"doNotAllow": [
|
|
1009
|
+
"import_leads",
|
|
1010
|
+
"list_senders",
|
|
1011
|
+
"start_campaign",
|
|
1012
|
+
"generate_messages"
|
|
1013
|
+
],
|
|
2324
1014
|
"hardRules": [
|
|
2325
1015
|
"critique_failure_never_escalates",
|
|
2326
1016
|
"critique_sample_size_bounded_by_config",
|
|
2327
1017
|
"critics_fixed_at_targeting_copy_voice",
|
|
2328
1018
|
"synthesis_enforces_phase_84_token_contract",
|
|
2329
1019
|
"opus_reserved_for_highest_value_subset",
|
|
2330
|
-
"proposed_token_never_persisted_in_rewrite"
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
"
|
|
1020
|
+
"proposed_token_never_persisted_in_rewrite"
|
|
1021
|
+
],
|
|
1022
|
+
"waitFor": [
|
|
1023
|
+
"review_batch_ready",
|
|
1024
|
+
"sample_revision_required"
|
|
2334
1025
|
],
|
|
2335
|
-
"watchRequired": true,
|
|
2336
|
-
"waitFor": ["review_batch_ready", "sample_revision_required"],
|
|
2337
1026
|
"transitions": {
|
|
2338
1027
|
"review_batch_ready": "awaiting-user-greenlight",
|
|
2339
1028
|
"escalation_triggered": "escalation"
|
|
@@ -2341,7 +1030,7 @@
|
|
|
2341
1030
|
},
|
|
2342
1031
|
{
|
|
2343
1032
|
"id": "awaiting-user-greenlight",
|
|
2344
|
-
"label": "
|
|
1033
|
+
"label": "Settings, sender, sequence, and greenlight",
|
|
2345
1034
|
"currentStepValue": "awaiting-user-greenlight",
|
|
2346
1035
|
"reference": "references/final-handoff-contract.md",
|
|
2347
1036
|
"onEnter": [
|
|
@@ -2351,7 +1040,7 @@
|
|
|
2351
1040
|
},
|
|
2352
1041
|
{
|
|
2353
1042
|
"tool": "list_senders",
|
|
2354
|
-
"purpose": "surface available connected senders
|
|
1043
|
+
"purpose": "surface available connected senders only at Settings"
|
|
2355
1044
|
},
|
|
2356
1045
|
{
|
|
2357
1046
|
"tool": "update_campaign",
|
|
@@ -2360,24 +1049,16 @@
|
|
|
2360
1049
|
"watchNarration.stage": "review-ready"
|
|
2361
1050
|
},
|
|
2362
1051
|
"purpose": "park the watched UI on Settings before sender selection",
|
|
2363
|
-
"watchNarrationRule": "Say message review is complete and the browser is now on Settings so the user can connect or choose a sender. Include
|
|
2364
|
-
},
|
|
2365
|
-
{
|
|
2366
|
-
"tool": "get_campaign_navigation_state",
|
|
2367
|
-
"purpose": "confirm the watched UI is oriented to Settings before sender selection",
|
|
2368
|
-
"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."
|
|
2369
1053
|
},
|
|
2370
1054
|
{
|
|
2371
1055
|
"action": "surface_sender_and_slack_handoff",
|
|
2372
|
-
"settingsUrlPattern": "/campaign-builder/{campaignId}/settings?mode={claude|codex}",
|
|
2373
1056
|
"requiredVisibleContent": [
|
|
2374
1057
|
"connect or select a LinkedIn sender",
|
|
2375
1058
|
"Slack reply review",
|
|
2376
|
-
"
|
|
1059
|
+
"recommended sequence",
|
|
2377
1060
|
"nothing starts until the user confirms launch"
|
|
2378
|
-
]
|
|
2379
|
-
"onNoAvailableSender": "surface settings link and wait for sender_connection_required",
|
|
2380
|
-
"onAvailableSender": "ask the user which connected sender to attach"
|
|
1061
|
+
]
|
|
2381
1062
|
},
|
|
2382
1063
|
{
|
|
2383
1064
|
"action": "ask_sender_selection",
|
|
@@ -2387,24 +1068,20 @@
|
|
|
2387
1068
|
"Use this connected sender",
|
|
2388
1069
|
"Connect a different sender in Settings",
|
|
2389
1070
|
"Pause here"
|
|
2390
|
-
]
|
|
2391
|
-
"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
|
+
]
|
|
2392
1072
|
},
|
|
2393
1073
|
{
|
|
2394
1074
|
"action": "attach_selected_sender",
|
|
2395
1075
|
"tool": "update_campaign",
|
|
2396
1076
|
"when": "user selected an available connected sender",
|
|
2397
1077
|
"requiredValues": {
|
|
2398
|
-
"senderIds": [
|
|
1078
|
+
"senderIds": [
|
|
1079
|
+
"{selectedSenderId}"
|
|
1080
|
+
],
|
|
2399
1081
|
"currentStep": "sequence",
|
|
2400
1082
|
"watchNarration.stage": "review-ready"
|
|
2401
1083
|
},
|
|
2402
|
-
"watchNarrationRule": "Say the sender was attached and the browser is moving to Sequence.
|
|
2403
|
-
},
|
|
2404
|
-
{
|
|
2405
|
-
"tool": "get_campaign_navigation_state",
|
|
2406
|
-
"purpose": "confirm the watched UI moved to Sequence after sender attach",
|
|
2407
|
-
"optional": true
|
|
1084
|
+
"watchNarrationRule": "Say the sender was attached and the browser is moving to Sequence."
|
|
2408
1085
|
},
|
|
2409
1086
|
{
|
|
2410
1087
|
"tool": "attach_recommended_sequence",
|
|
@@ -2414,48 +1091,21 @@
|
|
|
2414
1091
|
"currentStep": "send",
|
|
2415
1092
|
"watchNarration.stage": "review-ready"
|
|
2416
1093
|
},
|
|
2417
|
-
"
|
|
2418
|
-
"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; do not imply anything has sent yet."
|
|
2419
|
-
},
|
|
2420
|
-
{
|
|
2421
|
-
"tool": "get_campaign_navigation_state",
|
|
2422
|
-
"purpose": "confirm the watched UI is on Send before final launch greenlight",
|
|
2423
|
-
"optional": true
|
|
2424
|
-
},
|
|
2425
|
-
{
|
|
2426
|
-
"action": "surface_watch_link",
|
|
2427
|
-
"requires": [
|
|
2428
|
-
"campaign_shell_created",
|
|
2429
|
-
"rubrics_saved_to_campaign",
|
|
2430
|
-
"message_set_synced_to_brief"
|
|
2431
|
-
]
|
|
2432
|
-
},
|
|
2433
|
-
{
|
|
2434
|
-
"action": "surface_source_materialization_summary",
|
|
2435
|
-
"manifest": "lead-source-intake.json",
|
|
2436
|
-
"requiredFields": [
|
|
2437
|
-
"sourceType",
|
|
2438
|
-
"sourceRowCount",
|
|
2439
|
-
"reviewBatchImportedCount"
|
|
2440
|
-
],
|
|
2441
|
-
"note": "Say only the first review batch was enriched/messaged before greenlight."
|
|
2442
|
-
},
|
|
2443
|
-
{
|
|
2444
|
-
"action": "surface_orientation",
|
|
2445
|
-
"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."
|
|
2446
1095
|
},
|
|
2447
1096
|
{
|
|
2448
1097
|
"action": "ask_final_launch_greenlight",
|
|
2449
1098
|
"uses": "request_user_input",
|
|
2450
1099
|
"singleChoice": true,
|
|
2451
|
-
"choices": [
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
1100
|
+
"choices": [
|
|
1101
|
+
"Start campaign",
|
|
1102
|
+
"Review campaign first",
|
|
1103
|
+
"Pause here"
|
|
1104
|
+
],
|
|
1105
|
+
"onUserStart": "claude-greenlight"
|
|
2455
1106
|
}
|
|
2456
1107
|
],
|
|
2457
1108
|
"allowedTools": [
|
|
2458
|
-
"get_subskill_asset",
|
|
2459
1109
|
"get_campaign",
|
|
2460
1110
|
"get_campaign_navigation_state",
|
|
2461
1111
|
"list_senders",
|
|
@@ -2464,7 +1114,10 @@
|
|
|
2464
1114
|
"AskUserQuestion",
|
|
2465
1115
|
"request_user_input"
|
|
2466
1116
|
],
|
|
2467
|
-
"doNotAllow": [
|
|
1117
|
+
"doNotAllow": [
|
|
1118
|
+
"start_campaign",
|
|
1119
|
+
"import_leads"
|
|
1120
|
+
],
|
|
2468
1121
|
"autoStart": false,
|
|
2469
1122
|
"watchRequired": true,
|
|
2470
1123
|
"waitFor": [
|
|
@@ -2482,36 +1135,17 @@
|
|
|
2482
1135
|
"ready_to_launch": "awaiting-user-greenlight",
|
|
2483
1136
|
"user_greenlight": "claude-greenlight",
|
|
2484
1137
|
"ui_start_detected": "running"
|
|
2485
|
-
}
|
|
2486
|
-
"optionalRequiredArtifacts": ["lead-source-intake.json"]
|
|
1138
|
+
}
|
|
2487
1139
|
},
|
|
2488
1140
|
{
|
|
2489
1141
|
"id": "claude-greenlight",
|
|
2490
|
-
"label": "
|
|
1142
|
+
"label": "Explicit launch",
|
|
2491
1143
|
"reference": "references/final-handoff-contract.md",
|
|
2492
1144
|
"onEnter": [
|
|
2493
1145
|
{
|
|
2494
1146
|
"tool": "get_campaign",
|
|
2495
1147
|
"purpose": "detect_already_running"
|
|
2496
1148
|
},
|
|
2497
|
-
{
|
|
2498
|
-
"action": "short_circuit_if_already_running",
|
|
2499
|
-
"onAlreadyRunning": "running"
|
|
2500
|
-
},
|
|
2501
|
-
{
|
|
2502
|
-
"action": "validate_workspace_sender_invariant"
|
|
2503
|
-
},
|
|
2504
|
-
{
|
|
2505
|
-
"tool": "attach_recommended_sequence",
|
|
2506
|
-
"when": "sequence missing and campaign has attached sender",
|
|
2507
|
-
"purpose": "greenlight repair before approving/sending"
|
|
2508
|
-
},
|
|
2509
|
-
{
|
|
2510
|
-
"action": "bulk_approve_messages",
|
|
2511
|
-
"endpoint": "POST /api/v3/workflow-tables/cells/approve-batch",
|
|
2512
|
-
"reuseExisting": true,
|
|
2513
|
-
"doNotInventNewEndpoint": true
|
|
2514
|
-
},
|
|
2515
1149
|
{
|
|
2516
1150
|
"action": "verify_sequence_and_current_step_before_start",
|
|
2517
1151
|
"requiredState": [
|
|
@@ -2519,22 +1153,15 @@
|
|
|
2519
1153
|
"senderIds",
|
|
2520
1154
|
"sequenceTemplate",
|
|
2521
1155
|
"currentStep in awaiting-user-greenlight|claude-greenlight|send"
|
|
2522
|
-
]
|
|
2523
|
-
"onFailure": "surface recoverable pre-start refusal and remain in awaiting-user-greenlight"
|
|
1156
|
+
]
|
|
2524
1157
|
},
|
|
2525
1158
|
{
|
|
2526
1159
|
"tool": "start_campaign",
|
|
2527
|
-
"requiredFields": [
|
|
1160
|
+
"requiredFields": [
|
|
1161
|
+
"campaignId"
|
|
1162
|
+
],
|
|
2528
1163
|
"persistsCurrentStep": "running",
|
|
2529
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."
|
|
2530
|
-
},
|
|
2531
|
-
{
|
|
2532
|
-
"action": "surface_watch_link",
|
|
2533
|
-
"requires": [
|
|
2534
|
-
"campaign_shell_created",
|
|
2535
|
-
"sequence_attached",
|
|
2536
|
-
"start_campaign_succeeded"
|
|
2537
|
-
]
|
|
2538
1165
|
}
|
|
2539
1166
|
],
|
|
2540
1167
|
"allowedTools": [
|
|
@@ -2562,170 +1189,44 @@
|
|
|
2562
1189
|
"action": "surface_campaign_live_confirmation"
|
|
2563
1190
|
}
|
|
2564
1191
|
],
|
|
2565
|
-
"allowedTools": [
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
{
|
|
2570
|
-
"id": "escalation",
|
|
2571
|
-
"label": "Escalation (autonomous tail exit)",
|
|
2572
|
-
"reference": "references/escalation-ladder.md",
|
|
2573
|
-
"onEnter": [
|
|
2574
|
-
{
|
|
2575
|
-
"action": "preserve_current_step"
|
|
2576
|
-
},
|
|
2577
|
-
{
|
|
2578
|
-
"action": "write_diagnostic_and_history",
|
|
2579
|
-
"target": "workflow_table_notes_or_skill_artifact"
|
|
2580
|
-
},
|
|
2581
|
-
{
|
|
2582
|
-
"action": "resume_watch_link"
|
|
2583
|
-
},
|
|
2584
|
-
{
|
|
2585
|
-
"action": "ask_user_options",
|
|
2586
|
-
"choices": [
|
|
2587
|
-
"revise-brief",
|
|
2588
|
-
"revise-leads",
|
|
2589
|
-
"abort",
|
|
2590
|
-
"resume-from-step"
|
|
2591
|
-
]
|
|
2592
|
-
}
|
|
2593
|
-
],
|
|
2594
|
-
"allowedTools": ["AskUserQuestion", "request_user_input"],
|
|
2595
|
-
"doNotAllow": ["start_campaign", "import_leads"],
|
|
2596
|
-
"terminal": true
|
|
2597
|
-
},
|
|
2598
|
-
{
|
|
2599
|
-
"id": "revise-brief",
|
|
2600
|
-
"label": "Revise brief",
|
|
2601
|
-
"onEnter": [
|
|
2602
|
-
{
|
|
2603
|
-
"action": "route_back",
|
|
2604
|
-
"target": "phase-83-or-84"
|
|
2605
|
-
},
|
|
2606
|
-
{
|
|
2607
|
-
"action": "reset_draft_artifacts",
|
|
2608
|
-
"preserve": [],
|
|
2609
|
-
"delete": [
|
|
2610
|
-
"lead-review.md",
|
|
2611
|
-
"lead-sample.json",
|
|
2612
|
-
"lead-filter.md",
|
|
2613
|
-
"message-validation.md",
|
|
2614
|
-
"rubric.json"
|
|
2615
|
-
]
|
|
2616
|
-
}
|
|
1192
|
+
"allowedTools": [
|
|
1193
|
+
"get_campaign",
|
|
1194
|
+
"AskUserQuestion",
|
|
1195
|
+
"request_user_input"
|
|
2617
1196
|
],
|
|
2618
|
-
"
|
|
2619
|
-
|
|
2620
|
-
"terminal": true
|
|
2621
|
-
},
|
|
2622
|
-
{
|
|
2623
|
-
"id": "revise-leads",
|
|
2624
|
-
"label": "Revise leads",
|
|
2625
|
-
"onEnter": [
|
|
2626
|
-
{
|
|
2627
|
-
"action": "route_back",
|
|
2628
|
-
"target": "phase-84-find-leads"
|
|
2629
|
-
},
|
|
2630
|
-
{
|
|
2631
|
-
"action": "reset_draft_artifacts",
|
|
2632
|
-
"preserve": ["brief.md"],
|
|
2633
|
-
"delete": [
|
|
2634
|
-
"lead-review.md",
|
|
2635
|
-
"lead-sample.json",
|
|
2636
|
-
"lead-filter.md",
|
|
2637
|
-
"message-validation.md",
|
|
2638
|
-
"rubric.json"
|
|
2639
|
-
]
|
|
2640
|
-
}
|
|
1197
|
+
"doNotAllow": [
|
|
1198
|
+
"start_campaign"
|
|
2641
1199
|
],
|
|
2642
|
-
"allowedTools": ["AskUserQuestion", "request_user_input"],
|
|
2643
|
-
"doNotAllow": ["create_campaign", "save_rubrics", "import_leads"],
|
|
2644
1200
|
"terminal": true
|
|
2645
1201
|
},
|
|
2646
1202
|
{
|
|
2647
|
-
"id": "
|
|
2648
|
-
"label": "
|
|
2649
|
-
"
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
},
|
|
2654
|
-
{
|
|
2655
|
-
"action": "reset_draft_artifacts",
|
|
2656
|
-
"preserve": ["brief.md", "lead-review.md", "lead-sample.json"],
|
|
2657
|
-
"delete": ["lead-filter.md", "message-validation.md", "rubric.json"]
|
|
2658
|
-
}
|
|
1203
|
+
"id": "escalation",
|
|
1204
|
+
"label": "Escalation",
|
|
1205
|
+
"reference": "references/escalation-ladder.md",
|
|
1206
|
+
"allowedTools": [
|
|
1207
|
+
"AskUserQuestion",
|
|
1208
|
+
"request_user_input"
|
|
2659
1209
|
],
|
|
2660
|
-
"
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
},
|
|
2664
|
-
{
|
|
2665
|
-
"id": "revise-messaging",
|
|
2666
|
-
"label": "Revise messaging",
|
|
2667
|
-
"onEnter": [
|
|
2668
|
-
{
|
|
2669
|
-
"action": "route_back",
|
|
2670
|
-
"target": "phase-84-generate-message"
|
|
2671
|
-
},
|
|
2672
|
-
{
|
|
2673
|
-
"action": "reset_draft_artifacts",
|
|
2674
|
-
"preserve": [
|
|
2675
|
-
"brief.md",
|
|
2676
|
-
"lead-review.md",
|
|
2677
|
-
"lead-sample.json",
|
|
2678
|
-
"lead-filter.md"
|
|
2679
|
-
],
|
|
2680
|
-
"delete": ["message-validation.md"]
|
|
2681
|
-
}
|
|
1210
|
+
"doNotAllow": [
|
|
1211
|
+
"start_campaign",
|
|
1212
|
+
"import_leads"
|
|
2682
1213
|
],
|
|
2683
|
-
"
|
|
2684
|
-
|
|
2685
|
-
|
|
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
|
+
}
|
|
2686
1221
|
},
|
|
2687
1222
|
{
|
|
2688
1223
|
"id": "abort",
|
|
2689
1224
|
"label": "Abort",
|
|
2690
|
-
"
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
"target": ".aborted/"
|
|
2694
|
-
}
|
|
1225
|
+
"allowedTools": [
|
|
1226
|
+
"AskUserQuestion",
|
|
1227
|
+
"request_user_input"
|
|
2695
1228
|
],
|
|
2696
|
-
"allowedTools": ["AskUserQuestion", "request_user_input"],
|
|
2697
|
-
"doNotAllow": ["create_campaign", "save_rubrics", "import_leads"],
|
|
2698
1229
|
"terminal": true
|
|
2699
1230
|
}
|
|
2700
|
-
],
|
|
2701
|
-
"canonicalStateFields": [
|
|
2702
|
-
"campaignId",
|
|
2703
|
-
"watchUrl",
|
|
2704
|
-
"campaignBrief",
|
|
2705
|
-
"currentStep",
|
|
2706
|
-
"providerSearchAssociation",
|
|
2707
|
-
"selectedLeadListId",
|
|
2708
|
-
"workflowTableId",
|
|
2709
|
-
"leadScoringRubrics",
|
|
2710
|
-
"approvedMessageTemplate",
|
|
2711
|
-
"senderIds",
|
|
2712
|
-
"sequenceTemplate",
|
|
2713
|
-
"runningState"
|
|
2714
|
-
],
|
|
2715
|
-
"debugArtifacts": [
|
|
2716
|
-
"brief.md",
|
|
2717
|
-
"campaign-shell.json",
|
|
2718
|
-
"lead-source-intake.json",
|
|
2719
|
-
"lead-review.md",
|
|
2720
|
-
"lead-sample.json",
|
|
2721
|
-
"lead-filter.md",
|
|
2722
|
-
"rubric.json",
|
|
2723
|
-
"message-validation.md",
|
|
2724
|
-
"message-prep.md",
|
|
2725
|
-
"message-candidate-drafts.md",
|
|
2726
|
-
"message-review.md",
|
|
2727
|
-
"message-review-decision.md",
|
|
2728
|
-
"approval-packet.md",
|
|
2729
|
-
"commit-gate-decision.md"
|
|
2730
1231
|
]
|
|
2731
1232
|
}
|