@sellable/mcp 0.1.344 → 0.1.346
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/setup-evergreen-campaigns.d.ts +18 -0
- package/dist/tools/setup-evergreen-campaigns.js +16 -2
- package/package.json +1 -1
- package/skills/create-campaign-v2/references/final-handoff-contract.md +14 -1
- package/skills/create-campaign-v2-tail/SKILL.md +16 -1
- package/skills/create-evergreen-campaigns/SKILL.md +58 -12
|
@@ -4,6 +4,8 @@ type SetupEvergreenCampaignsInput = {
|
|
|
4
4
|
yolo?: boolean;
|
|
5
5
|
allConnectedSenders?: boolean;
|
|
6
6
|
selectedSenderIds?: string[];
|
|
7
|
+
postEngagerSenderIds?: string[];
|
|
8
|
+
sharedSenderIds?: string[];
|
|
7
9
|
bindings?: Array<{
|
|
8
10
|
laneKey: string;
|
|
9
11
|
campaignId: string;
|
|
@@ -45,6 +47,22 @@ export declare const setupEvergreenCampaignsToolDefinitions: {
|
|
|
45
47
|
maxItems: number;
|
|
46
48
|
description: string;
|
|
47
49
|
};
|
|
50
|
+
postEngagerSenderIds: {
|
|
51
|
+
type: string;
|
|
52
|
+
items: {
|
|
53
|
+
type: string;
|
|
54
|
+
};
|
|
55
|
+
maxItems: number;
|
|
56
|
+
description: string;
|
|
57
|
+
};
|
|
58
|
+
sharedSenderIds: {
|
|
59
|
+
type: string;
|
|
60
|
+
items: {
|
|
61
|
+
type: string;
|
|
62
|
+
};
|
|
63
|
+
maxItems: number;
|
|
64
|
+
description: string;
|
|
65
|
+
};
|
|
48
66
|
bindings: {
|
|
49
67
|
type: string;
|
|
50
68
|
maxItems: number;
|
|
@@ -6,7 +6,7 @@ async function postSetupEvergreenCampaigns(body) {
|
|
|
6
6
|
export const setupEvergreenCampaignsToolDefinitions = [
|
|
7
7
|
{
|
|
8
8
|
name: "setup_evergreen_campaigns",
|
|
9
|
-
description: "Evergreen campaign setup plan/verify command. Use plan mode first to inspect exact workspace/sender/campaign/table/source state and receive immutable lane packets for one Post Engagers lane per
|
|
9
|
+
description: "Evergreen campaign setup plan/verify command. Use plan mode first to inspect exact workspace/sender/campaign/table/source state and receive immutable lane packets. `selectedSenderIds` is a legacy shorthand for both scopes; prefer `postEngagerSenderIds` for the Post Engagers sender scope and `sharedSenderIds` for the shared lane sender scope when they differ. The command plans one Post Engagers lane per post-engager sender plus shared Signal Discovery and Shared Cold Fallback lanes for the shared sender set. yolo is only a parent-skill auto-execution hint for safe lane packets; this backend command remains read-only in plan mode and verifies receipts in verify mode. When safe-yolo needs normal setup work, the parent skill may ask for bounded delegated approval: one approval over the current planRevision, selected action ids, caps, allowed side-effect classes, and stop conditions lets lane workers execute without per-substep approval while staying inside that packet. Lane workers must execute creation, source import, create-campaign workflow steps, generate-messages, sequence attachment, and review readiness through existing create-campaign workflow/subskills, then return receipts here for verification. This command does not launch campaigns, does not schedule sends, does not assign scheduler-owned send fields, does not archive/delete cleanup targets, and does not spend paid credits.",
|
|
10
10
|
inputSchema: {
|
|
11
11
|
type: "object",
|
|
12
12
|
properties: {
|
|
@@ -32,7 +32,19 @@ export const setupEvergreenCampaignsToolDefinitions = [
|
|
|
32
32
|
type: "array",
|
|
33
33
|
items: { type: "string" },
|
|
34
34
|
maxItems: 25,
|
|
35
|
-
description: "
|
|
35
|
+
description: "Legacy shorthand: exact OutboundSenderIdentity ids for both sender-owned Post Engagers lanes and shared-lane sender set. Prefer scoped fields when those differ.",
|
|
36
|
+
},
|
|
37
|
+
postEngagerSenderIds: {
|
|
38
|
+
type: "array",
|
|
39
|
+
items: { type: "string" },
|
|
40
|
+
maxItems: 25,
|
|
41
|
+
description: "Exact OutboundSenderIdentity ids that should receive sender-owned Post Engagers lanes.",
|
|
42
|
+
},
|
|
43
|
+
sharedSenderIds: {
|
|
44
|
+
type: "array",
|
|
45
|
+
items: { type: "string" },
|
|
46
|
+
maxItems: 25,
|
|
47
|
+
description: "Exact OutboundSenderIdentity ids attached to shared Signal Discovery and Shared Cold Fallback lanes.",
|
|
36
48
|
},
|
|
37
49
|
bindings: {
|
|
38
50
|
type: "array",
|
|
@@ -78,6 +90,8 @@ export function setupEvergreenCampaigns(input) {
|
|
|
78
90
|
depth: input.depth,
|
|
79
91
|
allConnectedSenders: input.allConnectedSenders,
|
|
80
92
|
selectedSenderIds: input.selectedSenderIds,
|
|
93
|
+
postEngagerSenderIds: input.postEngagerSenderIds,
|
|
94
|
+
sharedSenderIds: input.sharedSenderIds,
|
|
81
95
|
bindings: input.bindings,
|
|
82
96
|
planRevision: input.planRevision,
|
|
83
97
|
selectedActionIds: input.selectedActionIds,
|
package/package.json
CHANGED
|
@@ -63,6 +63,15 @@ currentStep: "sequence" })` to attach the sender via the v3 senders route and
|
|
|
63
63
|
and Paid InMail Campaign is only an explicit paid-InMail opt-in because it
|
|
64
64
|
can spend InMail credits. If that response does not persist `currentStep:
|
|
65
65
|
"send"`, call `update_campaign({ campaignId, currentStep: "send" })`.
|
|
66
|
+
Then reread `get_campaign({ campaignId })` and `list_tables()` and verify the
|
|
67
|
+
current `workflowTableId` has `hasSequence:true`. A campaign-level
|
|
68
|
+
`SEQUENCE_EXISTS` response is not enough when `confirm_lead_list` or another
|
|
69
|
+
copy step has moved the campaign to a new current campaign table while an old
|
|
70
|
+
stale shell table still owns the sequence columns. In that stale-shell case,
|
|
71
|
+
either repair only the current workflowTableId with `attach_sequence` using
|
|
72
|
+
the same non-paid product template the recommended selector would have chosen,
|
|
73
|
+
or stop and report the stale-shell sequence blocker if replacement was not
|
|
74
|
+
explicitly approved. Never choose a paid-InMail template for this repair.
|
|
66
75
|
9. Surface the `handoff.orientation` string from `auto-execute.yaml` and
|
|
67
76
|
summarize the visible Settings/Sequence/Send state without repeating the
|
|
68
77
|
watch URL.
|
|
@@ -141,7 +150,11 @@ order, atomically:
|
|
|
141
150
|
2. **Validate sender + sequence state.** If no sender is attached, refuse start
|
|
142
151
|
and return the Settings link. If no sequence is attached but a sender is
|
|
143
152
|
attached, call `attach_recommended_sequence({ campaignId, currentStep:
|
|
144
|
-
"send" })` before approving messages
|
|
153
|
+
"send" })` before approving messages, then rerun the precondition check against
|
|
154
|
+
the current workflowTableId rather than an older shell table. If
|
|
155
|
+
`SEQUENCE_EXISTS` only proves an old shell while the current table lacks
|
|
156
|
+
`hasSequence:true`, stop or perform the explicitly approved stale-shell
|
|
157
|
+
current-table repair before any launch.
|
|
145
158
|
3. **Approve generated messages** through the bounded or broad path:
|
|
146
159
|
- If the user asked for an exact send count, such as "schedule 250 sends",
|
|
147
160
|
verify the preparation job approved only the bounded prepared cohort for
|
|
@@ -68,6 +68,7 @@ Step 16 — awaiting-user-greenlight
|
|
|
68
68
|
ask the user which connected sender to attach; in explicit UAT safe mode only, use the safe mock sender
|
|
69
69
|
update_campaign(senderIds=[selectedSenderId], currentStep=sequence)
|
|
70
70
|
attach_recommended_sequence({ campaignId, currentStep: "send" }) # tier-aware: premium/SN -> If Open Profile->INMAIL_OPEN, else INVITE->accepted->DM
|
|
71
|
+
reread get_campaign + list_tables; verify hasSequence:true on the current workflowTableId, not an older shell table
|
|
71
72
|
if the attach response did not move the UI: update_campaign(currentStep=send)
|
|
72
73
|
surface campaign setup orientation + final launch choices without repeating the watch URL
|
|
73
74
|
STOP. DO NOT call start_campaign. DO NOT move to running without explicit launch greenlight.
|
|
@@ -81,7 +82,13 @@ hand-author a `version: 2` template with nodes, branches, and
|
|
|
81
82
|
entryNodeId — that's error-prone mid-long-context (galley-off UAT
|
|
82
83
|
`20260420T195732Z` failed because Claude hit "Invalid node type" and
|
|
83
84
|
tried to debug via forbidden Bash/Glob calls). Use `attach_sequence`
|
|
84
|
-
only when the caller explicitly needs a custom non-recommended cadence
|
|
85
|
+
only when the caller explicitly needs a custom non-recommended cadence, or when
|
|
86
|
+
you have just reread the campaign after `confirm_lead_list` and proved the
|
|
87
|
+
current campaign table has no sequence while an older stale shell table is
|
|
88
|
+
causing campaign-level `SEQUENCE_EXISTS`. In that stale-shell repair case, use
|
|
89
|
+
`attach_sequence` on the current workflowTableId with the same non-paid product
|
|
90
|
+
template the backend would select; never choose a paid-InMail template and never
|
|
91
|
+
repair a table other than the current workflowTableId.
|
|
85
92
|
|
|
86
93
|
Hard gates — if you find yourself about to violate any of these, stop
|
|
87
94
|
first:
|
|
@@ -532,6 +539,14 @@ Shape:
|
|
|
532
539
|
opt-in because it can spend InMail credits. If the tool response
|
|
533
540
|
does not persist `currentStep: "send"`, call
|
|
534
541
|
`update_campaign({ campaignId, currentStep: "send" })`.
|
|
542
|
+
Then reread `get_campaign({ campaignId })` and `list_tables()` and verify the
|
|
543
|
+
returned current workflowTableId has `hasSequence:true`. If
|
|
544
|
+
`attach_recommended_sequence` returned `SEQUENCE_EXISTS` but the current table
|
|
545
|
+
still has `hasSequence:false`, do not continue to launch handoff from that
|
|
546
|
+
stale shell proof. Repair only the current workflowTableId with
|
|
547
|
+
`attach_sequence` using the same non-paid product template the recommended
|
|
548
|
+
selector would have chosen, or stop and report the stale-shell sequence
|
|
549
|
+
blocker if replacement was not explicitly approved.
|
|
535
550
|
9. Surface the `handoff.orientation` string from `auto-execute.yaml` without
|
|
536
551
|
repeating the watch URL.
|
|
537
552
|
10. Ask the final launch greenlight with the structured question function:
|
|
@@ -60,17 +60,34 @@ plan returns lane packets.
|
|
|
60
60
|
|
|
61
61
|
Plan shape:
|
|
62
62
|
|
|
63
|
-
- one Post Engagers lane per
|
|
64
|
-
- one shared Signal Discovery lane
|
|
65
|
-
- one shared Cold Fallback lane
|
|
63
|
+
- one Post Engagers lane per sender in the **Post Engagers sender scope**;
|
|
64
|
+
- one shared Signal Discovery lane for the **shared lane sender scope**;
|
|
65
|
+
- one shared Cold Fallback lane for the **shared lane sender scope**;
|
|
66
66
|
- explicit existing campaign/table bindings when the user points at a canonical
|
|
67
67
|
lane. Pass those exact ids to the plan and reuse/verify them instead of
|
|
68
68
|
creating duplicates.
|
|
69
69
|
- If a user supplies canonical ids, reuse/verify them instead of creating duplicates.
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
Use `selectedSenderIds` only as a legacy shorthand when the same senders should
|
|
72
|
+
get sender-owned Post Engagers lanes and attach to shared lanes. When the scopes
|
|
73
|
+
differ, pass both explicit arrays:
|
|
74
|
+
|
|
75
|
+
- `postEngagerSenderIds`: only senders that should have sender-owned Post
|
|
76
|
+
Engagers campaigns.
|
|
77
|
+
- `sharedSenderIds`: senders attached to the shared Signal Discovery and Shared
|
|
78
|
+
Cold Fallback campaigns.
|
|
79
|
+
|
|
80
|
+
If the operator says a sender is shared-only, do not create a Post Engagers lane
|
|
81
|
+
for that shared-only sender. Example: if Justin already has a Post Engagers
|
|
82
|
+
campaign and Jell/Hulan should only participate in the two shared campaigns,
|
|
83
|
+
call `setup_evergreen_campaigns` with `postEngagerSenderIds:["<justin id>"]`
|
|
84
|
+
and `sharedSenderIds:["<justin id>","<jell or hulan id>"]`.
|
|
85
|
+
|
|
86
|
+
When senders are ambiguous, ask which sender ids belong in the Post Engagers
|
|
87
|
+
sender scope and which belong in the shared lane sender scope before planning.
|
|
88
|
+
If the operator says all connected senders for both scopes, pass
|
|
89
|
+
`allConnectedSenders` and let the command return exact selected sender ids or
|
|
90
|
+
blockers.
|
|
74
91
|
|
|
75
92
|
`--yolo` is supported, but it is a safety-scoped execution mode, not a cleanup
|
|
76
93
|
or launch permission. With `--yolo`, pass `yolo:true` to
|
|
@@ -166,22 +183,51 @@ Parent-thread handwritten copy or setting `currentStep` is not proof.
|
|
|
166
183
|
- The first review batch exists and at least 3 review rows have generated
|
|
167
184
|
messages from the approved brief. If fewer than 3 usable rows exist, report
|
|
168
185
|
the actual count and why.
|
|
186
|
+
If a bounded preparation job requested more than the minimum but already
|
|
187
|
+
met the minimum generated-message floor, do not stall on a single bad review row once a fresh status/readiness check shows no queued, processing, or active cells; record the shortfall, name the failed/empty-row reason when
|
|
188
|
+
available, and continue with route-proof review rather than expanding source
|
|
189
|
+
or waiting forever.
|
|
169
190
|
- At least one generated row is approved as a route-proof gate. If zero rows
|
|
170
191
|
are approved and the prompt explicitly asked for full/customer-ready
|
|
171
192
|
completion, approve exactly one quality-valid generated row. If one or more
|
|
172
193
|
rows are already approved, do not add more approvals during evergreen
|
|
173
194
|
completion. Never broad approve all rows.
|
|
174
|
-
- The recommended non-paid sequence is attached
|
|
175
|
-
on Send. Use
|
|
176
|
-
|
|
177
|
-
|
|
195
|
+
- The recommended non-paid sequence is attached to the current campaign
|
|
196
|
+
table, and the watched campaign is on Send. Use
|
|
197
|
+
`attach_recommended_sequence({ campaignId, currentStep:"send" })` when a
|
|
198
|
+
safe attach is needed. After `confirm_lead_list` or any source-list copy,
|
|
199
|
+
immediately reread `get_campaign({ campaignId })`; the returned
|
|
200
|
+
`workflowTableId` is the current campaign table. Cross-check that exact
|
|
201
|
+
current workflowTableId with `list_tables` and require `hasSequence:true`
|
|
202
|
+
before reporting completion. If a stale shell table has sequence columns but
|
|
203
|
+
the current campaign table does not, `SEQUENCE_EXISTS` is not enough:
|
|
204
|
+
record the stale shell table id, then repair the current workflowTableId
|
|
205
|
+
with `attach_sequence` using the same non-paid product template
|
|
206
|
+
`attach_recommended_sequence` would have selected. Never use a paid-InMail
|
|
207
|
+
template and never attach/replace sequence outside the current table unless
|
|
208
|
+
the current lane packet explicitly allowed sequence repair.
|
|
178
209
|
- No scheduled, queued outbound, sent outbound, campaign launch, or paid
|
|
179
210
|
InMail spend is created by this skill.
|
|
180
211
|
4. **Verify each slot** after create/reuse/repair:
|
|
181
212
|
- `get_campaign` shows the campaign exists, remains unlaunched, and has the expected workflow table.
|
|
182
213
|
- Builder truth must match dashboard truth. `currentStep:"running"` is valid only when the linked table has `campaignStatus:"ACTIVE"`. For a `PAUSED` or `ARCHIVED` campaign/table, repair or flag stale `currentStep:"running"` back to launch review (`send` / review-ready) before reporting the slot done. Never call `start_campaign` just to make a stale `running` step true.
|
|
183
|
-
- Send/action lanes such as Post Engagers have a sequence attached
|
|
184
|
-
|
|
214
|
+
- Send/action lanes such as Post Engagers have a sequence attached on the
|
|
215
|
+
exact current campaign table. Use `list_tables({ hasSequence: true })` as a
|
|
216
|
+
quick cross-check, but do not treat that filter as the only proof. If the
|
|
217
|
+
canonical current campaign table is missing from the sequence-filtered
|
|
218
|
+
table list and `attach_recommended_sequence({ campaignId })` returns
|
|
219
|
+
`SEQUENCE_EXISTS`, inspect whether a stale shell table owns the sequence.
|
|
220
|
+
For a customer-visible completion run, stale shell proof is not completion:
|
|
221
|
+
rerun the current-table repair above or report `blocked: stale_shell_sequence`.
|
|
222
|
+
- Only use `attach_recommended_sequence({ campaignId })` for a send-lane
|
|
223
|
+
sequence repair/precheck when the target is a canonical prod slot and the
|
|
224
|
+
invoking prompt allows sequence repair. Call it at most once without
|
|
225
|
+
`confirmed`; a successful response is `repaired`. Treat `SEQUENCE_EXISTS` as
|
|
226
|
+
non-mutating proof only when the current table also has `hasSequence:true`.
|
|
227
|
+
Never call `attach_recommended_sequence` or `attach_sequence` with
|
|
228
|
+
`confirmed:true` in evergreen automation unless the user explicitly asks to
|
|
229
|
+
replace an existing sequence or the approved lane packet allows current
|
|
230
|
+
table stale-shell repair.
|
|
185
231
|
- Do not report `source-only/no sequence expected` for any named evergreen
|
|
186
232
|
campaign that appears in Campaigns, has a CampaignOffer ID, or is backed by
|
|
187
233
|
a campaign dashboard table. Shared Signal Discovery and Shared Cold
|