@sellable/mcp 0.1.100 → 0.1.102
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/sequencer.d.ts +7 -0
- package/dist/tools/sequencer.js +7 -0
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +14 -10
- package/skills/create-campaign-v2/SKILL.md +21 -9
- package/skills/create-campaign-v2/core/flow.v2.json +89 -8
- package/skills/create-campaign-v2/references/final-handoff-contract.md +43 -26
- package/skills/create-campaign-v2-tail/SKILL.md +43 -19
|
@@ -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
|
@@ -155,7 +155,8 @@ for them. The link is for deeper inspection; never use it as a substitute for
|
|
|
155
155
|
showing the content in chat.
|
|
156
156
|
|
|
157
157
|
Never mention MCP namespaces, prompt chunking, plugin cache paths, missing
|
|
158
|
-
linked skill versions, runbooks,
|
|
158
|
+
linked skill versions, runbooks, npm/package details, repo-local files, VPS or
|
|
159
|
+
browser automation limitations, or local skill files in normal customer-facing
|
|
159
160
|
copy.
|
|
160
161
|
|
|
161
162
|
## Codex Watch Browser Handoff
|
|
@@ -173,16 +174,17 @@ In Codex Desktop, when in-app browser control is available, open the returned wa
|
|
|
173
174
|
I’ll open the campaign view and keep it in sync as I build.
|
|
174
175
|
```
|
|
175
176
|
|
|
176
|
-
If browser control is unavailable,
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
orientation checks.
|
|
177
|
+
If browser control is unavailable, provide the watch link without discussing the
|
|
178
|
+
runtime limitation. In off-desktop Codex runs, make the signed link easy to
|
|
179
|
+
copy/open, then continue with explicit customer-facing campaign progress and
|
|
180
|
+
`get_campaign_navigation_state` orientation checks.
|
|
181
181
|
Use this fallback shape:
|
|
182
182
|
|
|
183
183
|
```text
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
Watch link: {watchUrl}
|
|
185
|
+
|
|
186
|
+
I’ll keep the campaign brief, lead source, and message-review steps explicit
|
|
187
|
+
here as I build.
|
|
186
188
|
```
|
|
187
189
|
|
|
188
190
|
If opening the watch link lands on an auth, 404, permission, blank, or visible
|
|
@@ -195,7 +197,7 @@ it was opened and observed.
|
|
|
195
197
|
After every `update_campaign({ campaignId, currentStep })`, use
|
|
196
198
|
`get_campaign_navigation_state` when available as a compact orientation check:
|
|
197
199
|
match the browser-visible step to the saved campaign state, explain the current
|
|
198
|
-
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.
|
|
199
201
|
|
|
200
202
|
## Names To Use
|
|
201
203
|
|
|
@@ -566,7 +568,9 @@ updates.
|
|
|
566
568
|
the brief, `pick-provider` or the selected provider step while sourcing,
|
|
567
569
|
`filter-choice` after the 10-row review batch, `messages` or
|
|
568
570
|
`auto-execute-messaging` for message work, `validate-sample` for validation,
|
|
569
|
-
|
|
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.
|
|
570
574
|
7. Keep `selectedLeadListId` as the source list and `workflowTableId` as the
|
|
571
575
|
campaign table. Do not use disk files as the post-mint source of truth.
|
|
572
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
|
|
@@ -161,7 +167,9 @@ Optional debug/UAT draft directory, disabled in normal customer runs:
|
|
|
161
167
|
- Customer-facing progress updates must use product language. Say "quick
|
|
162
168
|
setup choices", "campaign brief", "lead sourcing", and "approval" instead of
|
|
163
169
|
`request_user_input`, Default mode, MCP namespaces, plugin caches, prompt
|
|
164
|
-
loading, runbooks, local skill files, skill versions,
|
|
170
|
+
loading, runbooks, local skill files, skill versions, npm/package details,
|
|
171
|
+
repo-local files, VPS/off-desktop/browser automation limitations, or
|
|
172
|
+
"Sellable token".
|
|
165
173
|
"Quick question panel" is only acceptable when explaining a Codex/Claude setup
|
|
166
174
|
blocker.
|
|
167
175
|
- Before the 10-lead import/test batch, do not call `check_rubric`; Phase 84
|
|
@@ -613,9 +621,11 @@ There are four customer-visible gates in the net-new hosted flow:
|
|
|
613
621
|
one more messaging revision (`revise-messaging`). `approve-message` authorizes
|
|
614
622
|
syncing the approved message set into the campaign brief, saving rubrics,
|
|
615
623
|
importing the bounded 10-lead test batch, and queueing/observing that sample.
|
|
616
|
-
- The sender/settings/sequence handoff is the launch gate.
|
|
617
|
-
|
|
618
|
-
|
|
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.
|
|
619
629
|
|
|
620
630
|
Auto-continue without a structured question gate when the artifact says
|
|
621
631
|
`Status: confirmed` (or equivalent), confidence is high/medium, volume is
|
|
@@ -728,8 +738,10 @@ Required behavior:
|
|
|
728
738
|
- provider prompt preflight and interaction-mode approval are in-memory. On
|
|
729
739
|
resume or MCP restart, call `get_provider_prompt({ provider, campaignOfferId })`
|
|
730
740
|
again before any provider search/import; do not assume CampaignOffer state
|
|
731
|
-
proves preflight happened in this process.
|
|
732
|
-
|
|
741
|
+
proves preflight happened in this process. Immediately before `import_leads`,
|
|
742
|
+
reload the provider prompt in the same turn with
|
|
743
|
+
`get_provider_prompt({ provider, campaignOfferId })`, even when source preview
|
|
744
|
+
loaded it in a previous turn.
|
|
733
745
|
- if CampaignOffer campaignId is missing, stop and recover shell creation before
|
|
734
746
|
sourcing; do not run a campaignless source path in the active flow.
|
|
735
747
|
- do not import leads
|
|
@@ -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": [
|
|
@@ -840,6 +843,7 @@
|
|
|
840
843
|
},
|
|
841
844
|
{
|
|
842
845
|
"tool": "import_leads",
|
|
846
|
+
"sameTurnPreflight": "Immediately before import_leads, call get_provider_prompt({ provider, campaignOfferId }) in the same resumed turn, even if source discovery loaded the provider prompt earlier.",
|
|
843
847
|
"requiredFields": [
|
|
844
848
|
"campaignOfferId",
|
|
845
849
|
"targetLeadCount"
|
|
@@ -2138,16 +2142,76 @@
|
|
|
2138
2142
|
"purpose": "surface available connected senders if the campaign has none attached"
|
|
2139
2143
|
},
|
|
2140
2144
|
{
|
|
2141
|
-
"
|
|
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",
|
|
2142
2158
|
"settingsUrlPattern": "/campaign-builder/{campaignId}/settings?mode=claude",
|
|
2143
|
-
"
|
|
2144
|
-
|
|
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"
|
|
2145
2166
|
},
|
|
2146
2167
|
{
|
|
2147
|
-
"action": "
|
|
2148
|
-
"
|
|
2149
|
-
"
|
|
2150
|
-
"
|
|
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
|
|
2151
2215
|
},
|
|
2152
2216
|
{
|
|
2153
2217
|
"action": "surface_watch_link",
|
|
@@ -2172,13 +2236,26 @@
|
|
|
2172
2236
|
"fromConfig": "handoff.orientation"
|
|
2173
2237
|
},
|
|
2174
2238
|
{
|
|
2175
|
-
"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"
|
|
2176
2250
|
}
|
|
2177
2251
|
],
|
|
2178
2252
|
"allowedTools": [
|
|
2179
2253
|
"get_subskill_asset",
|
|
2180
2254
|
"get_campaign",
|
|
2255
|
+
"get_campaign_navigation_state",
|
|
2181
2256
|
"list_senders",
|
|
2257
|
+
"update_campaign",
|
|
2258
|
+
"attach_recommended_sequence",
|
|
2182
2259
|
"AskUserQuestion",
|
|
2183
2260
|
"request_user_input"
|
|
2184
2261
|
],
|
|
@@ -2189,14 +2266,18 @@
|
|
|
2189
2266
|
"autoStart": false,
|
|
2190
2267
|
"watchRequired": true,
|
|
2191
2268
|
"waitFor": [
|
|
2269
|
+
"sender_connection_required",
|
|
2192
2270
|
"sender_attached",
|
|
2193
2271
|
"sequence_attached",
|
|
2272
|
+
"ready_to_launch",
|
|
2194
2273
|
"user_greenlight",
|
|
2195
2274
|
"ui_start_detected"
|
|
2196
2275
|
],
|
|
2197
2276
|
"transitions": {
|
|
2277
|
+
"sender_connection_required": "awaiting-user-greenlight",
|
|
2198
2278
|
"sender_attached": "awaiting-user-greenlight",
|
|
2199
2279
|
"sequence_attached": "awaiting-user-greenlight",
|
|
2280
|
+
"ready_to_launch": "awaiting-user-greenlight",
|
|
2200
2281
|
"user_greenlight": "claude-greenlight",
|
|
2201
2282
|
"ui_start_detected": "running"
|
|
2202
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
|
-
|
|
53
|
+
10. Surface the `handoff.orientation` string from `auto-execute.yaml`
|
|
44
54
|
alongside the watch link so the user sees both the link and the
|
|
45
55
|
"what to do next" sentence.
|
|
46
|
-
|
|
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
|
-
messages.
|
|
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
|
|
|
@@ -407,7 +412,8 @@ row. Step 15 does not stall on critique.
|
|
|
407
412
|
|
|
408
413
|
## Step 16: awaiting-user-greenlight
|
|
409
414
|
|
|
410
|
-
Entered on `CampaignOffer.currentStep === "awaiting-user-greenlight"
|
|
415
|
+
Entered on `CampaignOffer.currentStep === "awaiting-user-greenlight"` or a
|
|
416
|
+
final-handoff UI step (`"settings"`, `"sequence"`, or `"send"`).
|
|
411
417
|
Full contract lives in `references/final-handoff-contract.md`.
|
|
412
418
|
|
|
413
419
|
Shape:
|
|
@@ -415,17 +421,35 @@ Shape:
|
|
|
415
421
|
1. Call `get_campaign({ campaignId })` and inspect sender/sequence state.
|
|
416
422
|
2. Call `list_senders()` so you can surface connected sender options if the
|
|
417
423
|
campaign has no attached sender.
|
|
418
|
-
3.
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
4.
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
424
|
+
3. Call `update_campaign({ campaignId, currentStep: "settings" })`, then use
|
|
425
|
+
`get_campaign_navigation_state` when available to confirm the watch link is
|
|
426
|
+
visibly on Settings.
|
|
427
|
+
4. Explain why the sender matters: Sellable needs a connected LinkedIn sender
|
|
428
|
+
before anything can send. Explain Slack reply review before launch: replies
|
|
429
|
+
and approvals need a place the team will actually monitor, so Slack should be
|
|
430
|
+
connected or intentionally skipped before launch.
|
|
431
|
+
5. If no connected sender exists, surface a direct Settings link:
|
|
432
|
+
`/campaign-builder/{campaignId}/settings?mode=claude`. Tell the user to
|
|
433
|
+
connect a sender there, then return here. STOP before sequence attach/start.
|
|
434
|
+
6. If connected senders exist but none is attached, ask the user which connected
|
|
435
|
+
sender to attach. Attach only after the user chooses. In explicit UAT safe
|
|
436
|
+
mode, use only the safe mock sender; never pick a real sender.
|
|
437
|
+
7. Call `update_campaign({ campaignId, senderIds: [selectedSenderId],
|
|
438
|
+
currentStep: "sequence" })` to attach the sender through the v3 senders
|
|
439
|
+
route and orient the watch link to Sequence.
|
|
440
|
+
8. Call `attach_recommended_sequence({ campaignId, currentStep: "send" })`
|
|
441
|
+
(bind the tier-recommended sequence to the campaign). If the tool response
|
|
442
|
+
does not persist `currentStep: "send"`, call
|
|
443
|
+
`update_campaign({ campaignId, currentStep: "send" })`.
|
|
444
|
+
9. Re-surface the `watchUrl` using `references/watch-link-handoff.md`.
|
|
445
|
+
10. Surface the `handoff.orientation` string from `auto-execute.yaml`
|
|
425
446
|
alongside the link.
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
447
|
+
11. Ask the final launch greenlight with the structured question function:
|
|
448
|
+
Start campaign, Review campaign first, or Pause here.
|
|
449
|
+
12. STOP unless the user explicitly chooses Start campaign. Do NOT call
|
|
450
|
+
`start_campaign` from Step 16 itself; that belongs only to the Claude
|
|
451
|
+
greenlight path. The autonomous tail ends here.
|
|
452
|
+
13. Make the credit boundary explicit in the handoff: only the first review
|
|
429
453
|
batch has been enriched/messaged; expanding to more leads requires a
|
|
430
454
|
separate user instruction.
|
|
431
455
|
|
|
@@ -441,9 +465,9 @@ campaign:
|
|
|
441
465
|
sequence is attached, `attach_recommended_sequence({ campaignId })`, (c)
|
|
442
466
|
bulk-approve queued messages via the EXISTING endpoint
|
|
443
467
|
`POST /api/v3/workflow-tables/cells/approve-batch` (do NOT invent a
|
|
444
|
-
new tool/endpoint), (d) `start_campaign({ campaignId })`,
|
|
445
|
-
`
|
|
446
|
-
|
|
468
|
+
new tool/endpoint), (d) `start_campaign({ campaignId })`, which persists
|
|
469
|
+
`currentStep: "running"`, (e) re-surface `watchUrl` plus a "campaign is live"
|
|
470
|
+
confirmation.
|
|
447
471
|
|
|
448
472
|
A Claude greenlight on an already-running campaign is a no-op
|
|
449
473
|
confirmation, NOT a duplicate start. Detect via `get_campaign` before
|