@sellable/mcp 0.1.101 → 0.1.103
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/dist/tools/prompts.js +2 -1
- package/dist/tools/sequencer.d.ts +7 -0
- package/dist/tools/sequencer.js +7 -0
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +4 -2
- package/skills/create-campaign-v2/SKILL.md +14 -6
- package/skills/create-campaign-v2/core/flow.v2.json +88 -8
- package/skills/create-campaign-v2/references/final-handoff-contract.md +45 -28
- package/skills/create-campaign-v2-tail/SKILL.md +53 -22
package/dist/tools/prompts.js
CHANGED
|
@@ -319,7 +319,8 @@ export function listSubskillPrompts(limit, includePublic, includeInternal) {
|
|
|
319
319
|
};
|
|
320
320
|
}
|
|
321
321
|
function markSubskillPromptLoaded(subskillName) {
|
|
322
|
-
if (subskillName === "create-campaign" ||
|
|
322
|
+
if (subskillName === "create-campaign" ||
|
|
323
|
+
subskillName === "create-campaign-v2") {
|
|
323
324
|
markCreateCampaignPromptLoaded();
|
|
324
325
|
}
|
|
325
326
|
if (subskillName === "research") {
|
|
@@ -30,6 +30,7 @@ export type AttachSequenceResponse = {
|
|
|
30
30
|
export type AttachRecommendedSequenceInput = {
|
|
31
31
|
campaignId: string;
|
|
32
32
|
confirmed?: boolean;
|
|
33
|
+
currentStep?: string;
|
|
33
34
|
};
|
|
34
35
|
export type AttachRecommendedSequenceResponse = {
|
|
35
36
|
success: boolean;
|
|
@@ -74,6 +75,7 @@ export declare const sequencerToolDefinitions: ({
|
|
|
74
75
|
template?: undefined;
|
|
75
76
|
confirmed?: undefined;
|
|
76
77
|
campaignId?: undefined;
|
|
78
|
+
currentStep?: undefined;
|
|
77
79
|
};
|
|
78
80
|
required: string[];
|
|
79
81
|
};
|
|
@@ -101,6 +103,7 @@ export declare const sequencerToolDefinitions: ({
|
|
|
101
103
|
senderLinkedinUrl?: undefined;
|
|
102
104
|
sequenceActions?: undefined;
|
|
103
105
|
campaignId?: undefined;
|
|
106
|
+
currentStep?: undefined;
|
|
104
107
|
};
|
|
105
108
|
required: string[];
|
|
106
109
|
};
|
|
@@ -118,6 +121,10 @@ export declare const sequencerToolDefinitions: ({
|
|
|
118
121
|
type: string;
|
|
119
122
|
description: string;
|
|
120
123
|
};
|
|
124
|
+
currentStep: {
|
|
125
|
+
type: string;
|
|
126
|
+
description: string;
|
|
127
|
+
};
|
|
121
128
|
name?: undefined;
|
|
122
129
|
senderId?: undefined;
|
|
123
130
|
clientProspectId?: undefined;
|
package/dist/tools/sequencer.js
CHANGED
|
@@ -81,6 +81,10 @@ export const sequencerToolDefinitions = [
|
|
|
81
81
|
type: "boolean",
|
|
82
82
|
description: "Set true to overwrite existing sequence columns if the campaign already has a sequence attached",
|
|
83
83
|
},
|
|
84
|
+
currentStep: {
|
|
85
|
+
type: "string",
|
|
86
|
+
description: "Optional CampaignOffer currentStep to persist with the sequence attach, usually 'send' after the recommended sequence is bound.",
|
|
87
|
+
},
|
|
84
88
|
},
|
|
85
89
|
required: ["campaignId"],
|
|
86
90
|
},
|
|
@@ -178,6 +182,9 @@ export async function attachRecommendedSequence(input) {
|
|
|
178
182
|
return await api.put(`/api/v3/campaigns/${input.campaignId}/sequence`, {
|
|
179
183
|
autoSelectFromSenders: true,
|
|
180
184
|
confirmed: input.confirmed,
|
|
185
|
+
...(input.currentStep !== undefined
|
|
186
|
+
? { currentStep: input.currentStep }
|
|
187
|
+
: {}),
|
|
181
188
|
});
|
|
182
189
|
}
|
|
183
190
|
catch (error) {
|
package/package.json
CHANGED
|
@@ -197,7 +197,7 @@ it was opened and observed.
|
|
|
197
197
|
After every `update_campaign({ campaignId, currentStep })`, use
|
|
198
198
|
`get_campaign_navigation_state` when available as a compact orientation check:
|
|
199
199
|
match the browser-visible step to the saved campaign state, explain the current
|
|
200
|
-
state in one sentence, and only then continue. Sender selection belongs at Settings after message approval and 10-row validation.
|
|
200
|
+
state in one sentence, and only then continue. Sender selection belongs at Settings after message approval and 10-row validation. After message validation, use Settings to help the user connect or select a LinkedIn sender. Explain Slack reply review before launch. After sender selection, attach the recommended sequence and move the watched UI to Send. Do not start the campaign or trigger a live send unless the user explicitly confirms that launch action outside UAT.
|
|
201
201
|
|
|
202
202
|
## Names To Use
|
|
203
203
|
|
|
@@ -568,7 +568,9 @@ updates.
|
|
|
568
568
|
the brief, `pick-provider` or the selected provider step while sourcing,
|
|
569
569
|
`filter-choice` after the 10-row review batch, `messages` or
|
|
570
570
|
`auto-execute-messaging` for message work, `validate-sample` for validation,
|
|
571
|
-
|
|
571
|
+
`awaiting-user-greenlight` for the final handoff, `settings` for sender
|
|
572
|
+
selection, `sequence` after sender attach, and `send` once the recommended
|
|
573
|
+
sequence is attached. Do not advance the step backward.
|
|
572
574
|
7. Keep `selectedLeadListId` as the source list and `workflowTableId` as the
|
|
573
575
|
campaign table. Do not use disk files as the post-mint source of truth.
|
|
574
576
|
8. Do not ask the user to run another command.
|
|
@@ -107,9 +107,15 @@ Optional debug/UAT draft directory, disabled in normal customer runs:
|
|
|
107
107
|
import, saved rubrics, and the approved message template. It must never queue
|
|
108
108
|
workflow cells, attach a sequence, or start sending until rubrics are saved
|
|
109
109
|
and the approved message set has been synced into the campaign brief.
|
|
110
|
-
- Sender ownership
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
- Sender ownership belongs only to the final Settings handoff after message
|
|
111
|
+
validation. At that point the main thread may ask the user to connect or
|
|
112
|
+
select a LinkedIn sender, explain Slack reply review before launch, attach the
|
|
113
|
+
selected sender with `update_campaign({ senderIds, currentStep: "sequence" })`,
|
|
114
|
+
attach the recommended sequence, then move the watched UI to Send. It still
|
|
115
|
+
must not start sending until the user explicitly greenlights launch.
|
|
116
|
+
- senderIds persistence uses `update_campaign({ senderIds })`, which delegates
|
|
117
|
+
to the v3 senders route and never uses the v2 campaign-offers PUT for sender
|
|
118
|
+
persistence.
|
|
113
119
|
- Load `core/flow.v2.json` through
|
|
114
120
|
`get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "core/flow.v2.json" })`
|
|
115
121
|
at the start of the run and treat the returned JSON as the active state
|
|
@@ -615,9 +621,11 @@ There are four customer-visible gates in the net-new hosted flow:
|
|
|
615
621
|
one more messaging revision (`revise-messaging`). `approve-message` authorizes
|
|
616
622
|
syncing the approved message set into the campaign brief, saving rubrics,
|
|
617
623
|
importing the bounded 10-lead test batch, and queueing/observing that sample.
|
|
618
|
-
- The sender/settings/sequence handoff is the launch gate.
|
|
619
|
-
|
|
620
|
-
|
|
624
|
+
- The sender/settings/sequence handoff is the launch gate. After message
|
|
625
|
+
validation, use Settings to help the user connect or select a LinkedIn sender.
|
|
626
|
+
Explain Slack reply review before launch. After sender selection, attach the
|
|
627
|
+
recommended sequence and move the watched UI to Send. Starting the campaign
|
|
628
|
+
still waits until the user explicitly greenlights start.
|
|
621
629
|
|
|
622
630
|
Auto-continue without a structured question gate when the artifact says
|
|
623
631
|
`Status: confirmed` (or equivalent), confidence is high/medium, volume is
|
|
@@ -58,6 +58,9 @@
|
|
|
58
58
|
"message_set_synced_to_brief",
|
|
59
59
|
"review_batch_imported",
|
|
60
60
|
"settings_link_surfaced",
|
|
61
|
+
"sender_connection_required",
|
|
62
|
+
"sender_attached",
|
|
63
|
+
"ready_to_launch",
|
|
61
64
|
"sequence_attached"
|
|
62
65
|
],
|
|
63
66
|
"steps": [
|
|
@@ -2139,16 +2142,76 @@
|
|
|
2139
2142
|
"purpose": "surface available connected senders if the campaign has none attached"
|
|
2140
2143
|
},
|
|
2141
2144
|
{
|
|
2142
|
-
"
|
|
2145
|
+
"tool": "update_campaign",
|
|
2146
|
+
"requiredValues": {
|
|
2147
|
+
"currentStep": "settings"
|
|
2148
|
+
},
|
|
2149
|
+
"purpose": "park the watched UI on Settings before sender selection"
|
|
2150
|
+
},
|
|
2151
|
+
{
|
|
2152
|
+
"tool": "get_campaign_navigation_state",
|
|
2153
|
+
"purpose": "confirm the watched UI is oriented to Settings before sender selection",
|
|
2154
|
+
"optional": true
|
|
2155
|
+
},
|
|
2156
|
+
{
|
|
2157
|
+
"action": "surface_sender_and_slack_handoff",
|
|
2143
2158
|
"settingsUrlPattern": "/campaign-builder/{campaignId}/settings?mode=claude",
|
|
2144
|
-
"
|
|
2145
|
-
|
|
2159
|
+
"requiredVisibleContent": [
|
|
2160
|
+
"connect or select a LinkedIn sender",
|
|
2161
|
+
"Slack reply review",
|
|
2162
|
+
"nothing starts until the user confirms launch"
|
|
2163
|
+
],
|
|
2164
|
+
"onNoAvailableSender": "surface settings link and wait for sender_connection_required",
|
|
2165
|
+
"onAvailableSender": "ask the user which connected sender to attach"
|
|
2146
2166
|
},
|
|
2147
2167
|
{
|
|
2148
|
-
"action": "
|
|
2149
|
-
"
|
|
2150
|
-
"
|
|
2151
|
-
"
|
|
2168
|
+
"action": "ask_sender_selection",
|
|
2169
|
+
"uses": "request_user_input",
|
|
2170
|
+
"singleChoice": true,
|
|
2171
|
+
"choices": [
|
|
2172
|
+
"Use this connected sender",
|
|
2173
|
+
"Connect a different sender in Settings",
|
|
2174
|
+
"Pause here"
|
|
2175
|
+
],
|
|
2176
|
+
"uatSafety": "Only auto-select a mock/safe sender when an explicit UAT safe-mode sender is active; never select a real sender in UAT."
|
|
2177
|
+
},
|
|
2178
|
+
{
|
|
2179
|
+
"action": "attach_selected_sender",
|
|
2180
|
+
"tool": "update_campaign",
|
|
2181
|
+
"when": "user selected an available connected sender",
|
|
2182
|
+
"requiredValues": {
|
|
2183
|
+
"senderIds": [
|
|
2184
|
+
"{selectedSenderId}"
|
|
2185
|
+
],
|
|
2186
|
+
"currentStep": "sequence"
|
|
2187
|
+
}
|
|
2188
|
+
},
|
|
2189
|
+
{
|
|
2190
|
+
"tool": "get_campaign_navigation_state",
|
|
2191
|
+
"purpose": "confirm the watched UI moved to Sequence after sender attach",
|
|
2192
|
+
"optional": true
|
|
2193
|
+
},
|
|
2194
|
+
{
|
|
2195
|
+
"tool": "attach_recommended_sequence",
|
|
2196
|
+
"when": "after senderIds are attached",
|
|
2197
|
+
"requiredValues": {
|
|
2198
|
+
"campaignId": "{campaignId}",
|
|
2199
|
+
"currentStep": "send"
|
|
2200
|
+
},
|
|
2201
|
+
"purpose": "bind the tier-aware recommended sequence before the launch decision"
|
|
2202
|
+
},
|
|
2203
|
+
{
|
|
2204
|
+
"tool": "update_campaign",
|
|
2205
|
+
"when": "sequence attach response does not persist currentStep",
|
|
2206
|
+
"requiredValues": {
|
|
2207
|
+
"currentStep": "send"
|
|
2208
|
+
},
|
|
2209
|
+
"purpose": "show the Send tab once sender and sequence are ready"
|
|
2210
|
+
},
|
|
2211
|
+
{
|
|
2212
|
+
"tool": "get_campaign_navigation_state",
|
|
2213
|
+
"purpose": "confirm the watched UI is on Send before final launch greenlight",
|
|
2214
|
+
"optional": true
|
|
2152
2215
|
},
|
|
2153
2216
|
{
|
|
2154
2217
|
"action": "surface_watch_link",
|
|
@@ -2173,13 +2236,26 @@
|
|
|
2173
2236
|
"fromConfig": "handoff.orientation"
|
|
2174
2237
|
},
|
|
2175
2238
|
{
|
|
2176
|
-
"action": "
|
|
2239
|
+
"action": "ask_final_launch_greenlight",
|
|
2240
|
+
"uses": "request_user_input",
|
|
2241
|
+
"singleChoice": true,
|
|
2242
|
+
"choices": [
|
|
2243
|
+
"Start campaign",
|
|
2244
|
+
"Review campaign first",
|
|
2245
|
+
"Pause here"
|
|
2246
|
+
],
|
|
2247
|
+
"onUserStart": "claude-greenlight",
|
|
2248
|
+
"onReviewFirst": "awaiting-user-greenlight",
|
|
2249
|
+
"onPause": "awaiting-user-greenlight"
|
|
2177
2250
|
}
|
|
2178
2251
|
],
|
|
2179
2252
|
"allowedTools": [
|
|
2180
2253
|
"get_subskill_asset",
|
|
2181
2254
|
"get_campaign",
|
|
2255
|
+
"get_campaign_navigation_state",
|
|
2182
2256
|
"list_senders",
|
|
2257
|
+
"update_campaign",
|
|
2258
|
+
"attach_recommended_sequence",
|
|
2183
2259
|
"AskUserQuestion",
|
|
2184
2260
|
"request_user_input"
|
|
2185
2261
|
],
|
|
@@ -2190,14 +2266,18 @@
|
|
|
2190
2266
|
"autoStart": false,
|
|
2191
2267
|
"watchRequired": true,
|
|
2192
2268
|
"waitFor": [
|
|
2269
|
+
"sender_connection_required",
|
|
2193
2270
|
"sender_attached",
|
|
2194
2271
|
"sequence_attached",
|
|
2272
|
+
"ready_to_launch",
|
|
2195
2273
|
"user_greenlight",
|
|
2196
2274
|
"ui_start_detected"
|
|
2197
2275
|
],
|
|
2198
2276
|
"transitions": {
|
|
2277
|
+
"sender_connection_required": "awaiting-user-greenlight",
|
|
2199
2278
|
"sender_attached": "awaiting-user-greenlight",
|
|
2200
2279
|
"sequence_attached": "awaiting-user-greenlight",
|
|
2280
|
+
"ready_to_launch": "awaiting-user-greenlight",
|
|
2201
2281
|
"user_greenlight": "claude-greenlight",
|
|
2202
2282
|
"ui_start_detected": "running"
|
|
2203
2283
|
},
|
|
@@ -29,29 +29,42 @@ order (all before waiting for the user):
|
|
|
29
29
|
least one attached sender and whether a sequence is already attached.
|
|
30
30
|
2. Call `list_senders()` so the handoff can name available connected senders if
|
|
31
31
|
the campaign has none selected.
|
|
32
|
-
3.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
4.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
3. Call `update_campaign({ campaignId, currentStep: "settings" })` and use
|
|
33
|
+
`get_campaign_navigation_state` when available so the watch link visibly
|
|
34
|
+
lands on Settings before sender setup.
|
|
35
|
+
4. Explain sender setup and Slack in normal customer language: Sellable needs a
|
|
36
|
+
connected LinkedIn sender before anything can send, and Slack reply review
|
|
37
|
+
matters because replies and approvals need a channel the team will monitor.
|
|
38
|
+
5. If no connected sender exists, surface the campaign Settings link
|
|
39
|
+
`/campaign-builder/{campaignId}/settings?mode=claude`, tell the user to
|
|
40
|
+
connect a sender there, and STOP. Do not attach sequence and do not start.
|
|
41
|
+
6. If connected senders exist and no sender is attached, ask the user which
|
|
42
|
+
connected sender to attach. Attach only the chosen sender. In explicit UAT
|
|
43
|
+
safe mode, auto-select only the safe mock sender; never select a real sender.
|
|
44
|
+
7. Call `update_campaign({ campaignId, senderIds: [selectedSenderId],
|
|
45
|
+
currentStep: "sequence" })` to attach the sender via the v3 senders route and
|
|
46
|
+
move the watch link to Sequence.
|
|
47
|
+
8. Call `attach_recommended_sequence({ campaignId, currentStep: "send" })` to
|
|
48
|
+
bind the tier-aware recommended sequence. If that response does not persist
|
|
49
|
+
`currentStep: "send"`, call `update_campaign({ campaignId, currentStep:
|
|
50
|
+
"send" })`.
|
|
51
|
+
9. Re-surface the `watchUrl` using the exact block in
|
|
42
52
|
`references/watch-link-handoff.md`.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
10. Surface the `handoff.orientation` string from `auto-execute.yaml`
|
|
54
|
+
alongside the watch link so the user sees both the link and the
|
|
55
|
+
"what to do next" sentence.
|
|
56
|
+
11. Ask the final launch greenlight with the structured question function:
|
|
57
|
+
Start campaign, Review campaign first, or Pause here.
|
|
58
|
+
12. STOP unless the user explicitly chooses Start campaign. Do not call
|
|
59
|
+
`start_campaign` from Step 16 itself.
|
|
47
60
|
|
|
48
61
|
The final handoff must answer five customer questions in plain language:
|
|
49
62
|
|
|
50
63
|
- where to inspect the campaign (`watchUrl`)
|
|
51
64
|
- what is ready now (brief, filters/rubrics, review-batch leads, messages, and
|
|
52
|
-
sequence
|
|
53
|
-
- whether the next UI step is Settings
|
|
54
|
-
|
|
65
|
+
sequence after a sender is attached)
|
|
66
|
+
- whether the next UI step is Settings, Sequence, or Send
|
|
67
|
+
- why the selected LinkedIn sender and Slack reply review matter before launch
|
|
55
68
|
- what clicking Start does (approves/starts the campaign send path)
|
|
56
69
|
- how to revise (reply with what to change, or use the campaign UI)
|
|
57
70
|
- whether anything has started yet (nothing sends until the user starts)
|
|
@@ -67,8 +80,11 @@ When `lead-source-intake.json` exists, also answer:
|
|
|
67
80
|
- for `existing-lead-list`, that the source list was reused, not recreated
|
|
68
81
|
|
|
69
82
|
Use the exact state name `awaiting-user-greenlight` so logs and UX artifacts
|
|
70
|
-
can verify the stop point, but explain it in normal words: the
|
|
71
|
-
built
|
|
83
|
+
can verify the state-machine stop point, but explain it in normal words: the
|
|
84
|
+
campaign is built, sender/sequence setup is being completed, and nothing sends
|
|
85
|
+
until the user's final start decision. The watched UI may advance through
|
|
86
|
+
Settings, Sequence, and Send while this state-machine step remains the final
|
|
87
|
+
handoff.
|
|
72
88
|
|
|
73
89
|
The skill waits. It does not poll. A fresh continuation turn arrives
|
|
74
90
|
either because the user said something in chat (Claude greenlight path)
|
|
@@ -79,9 +95,9 @@ the UI.
|
|
|
79
95
|
|
|
80
96
|
### UI path
|
|
81
97
|
|
|
82
|
-
The user reviews messages in the watch link,
|
|
83
|
-
needed,
|
|
84
|
-
table UI (the existing "Approve all" button that wraps
|
|
98
|
+
The user reviews messages in the watch link, connects or selects a sender in
|
|
99
|
+
Settings when needed, reviews the recommended sequence, bulk-approves messages
|
|
100
|
+
in the workflow table UI (the existing "Approve all" button that wraps
|
|
85
101
|
`POST /api/v3/workflow-tables/cells/approve-batch`), and clicks "Start Campaign"
|
|
86
102
|
in the campaign-builder UI.
|
|
87
103
|
|
|
@@ -100,8 +116,8 @@ order, atomically:
|
|
|
100
116
|
if already running.
|
|
101
117
|
2. **Validate sender + sequence state.** If no sender is attached, refuse start
|
|
102
118
|
and return the Settings link. If no sequence is attached but a sender is
|
|
103
|
-
attached, call `attach_recommended_sequence({ campaignId
|
|
104
|
-
|
|
119
|
+
attached, call `attach_recommended_sequence({ campaignId, currentStep:
|
|
120
|
+
"send" })` before approving messages.
|
|
105
121
|
3. **Bulk-approve queued messages** via the existing endpoint
|
|
106
122
|
`POST /api/v3/workflow-tables/cells/approve-batch` with
|
|
107
123
|
`{ tableId }`.
|
|
@@ -191,10 +207,11 @@ does NOT silently proceed.
|
|
|
191
207
|
## Hard Rules
|
|
192
208
|
|
|
193
209
|
- The autonomous tail NEVER calls `start_campaign` on its own.
|
|
194
|
-
- Step 16
|
|
195
|
-
user signal.
|
|
196
|
-
- Step 16 routes to Settings before
|
|
197
|
-
- Step 16 routes to Sequence
|
|
210
|
+
- Step 16 may move the watched UI through Settings, Sequence, and Send, but it
|
|
211
|
+
NEVER transitions to `running` or calls `start_campaign` without a user signal.
|
|
212
|
+
- Step 16 routes to Settings before sender attach.
|
|
213
|
+
- Step 16 routes to Sequence after sender attach and before sequence attach.
|
|
214
|
+
- Step 16 routes to Send after the recommended sequence is attached.
|
|
198
215
|
- Prefer `attach_recommended_sequence`; use `attach_sequence` only for an
|
|
199
216
|
explicitly custom cadence.
|
|
200
217
|
- Bulk-approve in the Claude greenlight path uses the EXISTING
|
|
@@ -61,10 +61,14 @@ Step 15 — observe messaging
|
|
|
61
61
|
|
|
62
62
|
Step 16 — awaiting-user-greenlight
|
|
63
63
|
get_campaign + list_senders
|
|
64
|
-
|
|
65
|
-
if sender
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
update_campaign(currentStep=settings) + orient the watch link to Settings
|
|
65
|
+
if no connected sender exists: explain sender setup + Slack reply review, surface campaign settings link, and STOP
|
|
66
|
+
ask the user which connected sender to attach; in explicit UAT safe mode only, use the safe mock sender
|
|
67
|
+
update_campaign(senderIds=[selectedSenderId], currentStep=sequence)
|
|
68
|
+
attach_recommended_sequence({ campaignId, currentStep: "send" }) # tier-aware: premium/SN -> If Open Profile->INMAIL_OPEN, else INVITE->accepted->DM
|
|
69
|
+
if the attach response did not move the UI: update_campaign(currentStep=send)
|
|
70
|
+
re-surface watchUrl + review-batch orientation + final launch choices
|
|
71
|
+
STOP. DO NOT call start_campaign. DO NOT move to running without explicit launch greenlight.
|
|
68
72
|
```
|
|
69
73
|
|
|
70
74
|
**Prefer `attach_recommended_sequence` over `attach_sequence` in the
|
|
@@ -136,7 +140,8 @@ reuse the v1 `create-campaign` watch-mode pattern verbatim.
|
|
|
136
140
|
|
|
137
141
|
Resume currentStep names covered by this tail: `"auto-execute-leads"`,
|
|
138
142
|
`"validate-sample"`, `"auto-execute-messaging"`,
|
|
139
|
-
`"awaiting-user-greenlight"`,
|
|
143
|
+
`"awaiting-user-greenlight"`, `"settings"`, `"sequence"`, `"send"`, and
|
|
144
|
+
`"running"`. New mint-early runs normally
|
|
140
145
|
enter Step 13 from `"confirm-lead-list"`; the `"auto-execute-leads"` string is
|
|
141
146
|
kept for compatibility resumes.
|
|
142
147
|
|
|
@@ -308,6 +313,13 @@ awaiting-user-greenlight, or start-campaign. It must hand off as
|
|
|
308
313
|
`sample_revision_required` with the observed counts so the user can decide
|
|
309
314
|
whether the source or filter should change.
|
|
310
315
|
|
|
316
|
+
If the same source lane has already failed after a revision, do not present
|
|
317
|
+
another same-source revision as the recommended/default next action. Recommend
|
|
318
|
+
the strongest fallback lane first (for example, Sales Nav after repeated
|
|
319
|
+
Signals underfloor results), then offer revise-filter only if the imported rows
|
|
320
|
+
look close to ICP but the rubric is too strict. This prevents customer-visible
|
|
321
|
+
loops where the agent keeps asking to retry the same weak source.
|
|
322
|
+
|
|
311
323
|
When the sample passes the projected-pass floor, call
|
|
312
324
|
`update_campaign({ campaignId, currentStep: "auto-execute-messaging" })`
|
|
313
325
|
and orient the user that messaging will complete for the review batch only.
|
|
@@ -407,7 +419,8 @@ row. Step 15 does not stall on critique.
|
|
|
407
419
|
|
|
408
420
|
## Step 16: awaiting-user-greenlight
|
|
409
421
|
|
|
410
|
-
Entered on `CampaignOffer.currentStep === "awaiting-user-greenlight"
|
|
422
|
+
Entered on `CampaignOffer.currentStep === "awaiting-user-greenlight"` or a
|
|
423
|
+
final-handoff UI step (`"settings"`, `"sequence"`, or `"send"`).
|
|
411
424
|
Full contract lives in `references/final-handoff-contract.md`.
|
|
412
425
|
|
|
413
426
|
Shape:
|
|
@@ -415,19 +428,37 @@ Shape:
|
|
|
415
428
|
1. Call `get_campaign({ campaignId })` and inspect sender/sequence state.
|
|
416
429
|
2. Call `list_senders()` so you can surface connected sender options if the
|
|
417
430
|
campaign has no attached sender.
|
|
418
|
-
3.
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
4.
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
+
3. Call `update_campaign({ campaignId, currentStep: "settings" })`, then use
|
|
432
|
+
`get_campaign_navigation_state` when available to confirm the watch link is
|
|
433
|
+
visibly on Settings.
|
|
434
|
+
4. Explain why the sender matters: Sellable needs a connected LinkedIn sender
|
|
435
|
+
before anything can send. Explain Slack reply review before launch: replies
|
|
436
|
+
and approvals need a place the team will actually monitor, so Slack should be
|
|
437
|
+
connected or intentionally skipped before launch.
|
|
438
|
+
5. If no connected sender exists, surface a direct Settings link:
|
|
439
|
+
`/campaign-builder/{campaignId}/settings?mode=claude`. Tell the user to
|
|
440
|
+
connect a sender there, then return here. STOP before sequence attach/start.
|
|
441
|
+
6. If connected senders exist but none is attached, ask the user which connected
|
|
442
|
+
sender to attach. Attach only after the user chooses. In explicit UAT safe
|
|
443
|
+
mode, use only the safe mock sender; never pick a real sender.
|
|
444
|
+
7. Call `update_campaign({ campaignId, senderIds: [selectedSenderId],
|
|
445
|
+
currentStep: "sequence" })` to attach the sender through the v3 senders
|
|
446
|
+
route and orient the watch link to Sequence.
|
|
447
|
+
8. Call `attach_recommended_sequence({ campaignId, currentStep: "send" })`
|
|
448
|
+
(bind the tier-recommended sequence to the campaign). If the tool response
|
|
449
|
+
does not persist `currentStep: "send"`, call
|
|
450
|
+
`update_campaign({ campaignId, currentStep: "send" })`.
|
|
451
|
+
9. Re-surface the `watchUrl` using `references/watch-link-handoff.md`.
|
|
452
|
+
10. Surface the `handoff.orientation` string from `auto-execute.yaml`
|
|
453
|
+
alongside the link.
|
|
454
|
+
11. Ask the final launch greenlight with the structured question function:
|
|
455
|
+
Start campaign, Review campaign first, or Pause here.
|
|
456
|
+
12. STOP unless the user explicitly chooses Start campaign. Do NOT call
|
|
457
|
+
`start_campaign` from Step 16 itself; that belongs only to the Claude
|
|
458
|
+
greenlight path. The autonomous tail ends here.
|
|
459
|
+
13. Make the credit boundary explicit in the handoff: only the first review
|
|
460
|
+
batch has been enriched/messaged; expanding to more leads requires a
|
|
461
|
+
separate user instruction.
|
|
431
462
|
|
|
432
463
|
Two equally valid greenlight channels take Step 16 into a running
|
|
433
464
|
campaign:
|
|
@@ -441,9 +472,9 @@ campaign:
|
|
|
441
472
|
sequence is attached, `attach_recommended_sequence({ campaignId })`, (c)
|
|
442
473
|
bulk-approve queued messages via the EXISTING endpoint
|
|
443
474
|
`POST /api/v3/workflow-tables/cells/approve-batch` (do NOT invent a
|
|
444
|
-
new tool/endpoint), (d) `start_campaign({ campaignId })`,
|
|
445
|
-
`
|
|
446
|
-
|
|
475
|
+
new tool/endpoint), (d) `start_campaign({ campaignId })`, which persists
|
|
476
|
+
`currentStep: "running"`, (e) re-surface `watchUrl` plus a "campaign is live"
|
|
477
|
+
confirmation.
|
|
447
478
|
|
|
448
479
|
A Claude greenlight on an already-running campaign is a no-op
|
|
449
480
|
confirmation, NOT a duplicate start. Detect via `get_campaign` before
|