@sellable/mcp 0.1.451 → 0.1.453
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/server.js +4 -0
- package/dist/tools/refill-sends.js +14 -5
- package/dist/tools/refill-target-plan.d.ts +85 -0
- package/dist/tools/refill-target-plan.js +90 -0
- package/dist/tools/registry.js +2 -0
- package/package.json +1 -1
- package/skills/create-campaign/SKILL.md +1 -0
- package/skills/create-campaign-v2/references/gold-standard-message-examples.md +13 -0
- package/skills/refill-sends/SKILL.md +24 -7
- package/skills/refill-sends-workflow/SKILL.md +33 -16
package/dist/server.js
CHANGED
|
@@ -10,6 +10,7 @@ import { resolveCampaignFillRoute } from "./tools/campaign-fill-routing.js";
|
|
|
10
10
|
import { fillCampaignHorizon } from "./tools/campaign-horizon-fill.js";
|
|
11
11
|
import { cancelPrepareCampaignMessages, getPrepareCampaignMessagesStatus, startPrepareCampaignMessages, } from "./tools/campaign-message-preparation.js";
|
|
12
12
|
import { getCampaignRefillState } from "./tools/campaign-refill-state.js";
|
|
13
|
+
import { getRefillTargetPlan } from "./tools/refill-target-plan.js";
|
|
13
14
|
import { getCampaignTableSchema, queueCampaignCells, recordCampaignReviewBatch, reviseMessageTemplateAndRerun, selectCampaignCells, waitForCampaignProcessing, } from "./tools/campaign-processing.js";
|
|
14
15
|
import { archiveCampaign, createCampaign, duplicateCampaign, getCampaign, getCampaignMessagesPreview, getCampaigns, pauseCampaign, startCampaign, updateCampaign, updateCampaignBrief, } from "./tools/campaigns.js";
|
|
15
16
|
import { queueCells, updateCell } from "./tools/cells.js";
|
|
@@ -221,6 +222,9 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
221
222
|
case "get_campaign_refill_state":
|
|
222
223
|
result = await getCampaignRefillState(args);
|
|
223
224
|
break;
|
|
225
|
+
case "get_refill_target_plan":
|
|
226
|
+
result = await getRefillTargetPlan(args);
|
|
227
|
+
break;
|
|
224
228
|
case "refill_sends":
|
|
225
229
|
result = refillSendsCommand(args);
|
|
226
230
|
break;
|
|
@@ -142,6 +142,15 @@ export function refillSendsCommand(input = {}) {
|
|
|
142
142
|
},
|
|
143
143
|
firstOperationalSteps: [
|
|
144
144
|
'Load get_subskill_prompt({ subskillName: "refill-sends-workflow" }) before any product operation.',
|
|
145
|
+
`Call get_refill_target_plan({ intent: "${intent}"${input.campaignId ? `, campaignId: "${input.campaignId}"` : ""}${input.tableId ? `, tableId: "${input.tableId}"` : ""}${senderIds.length > 0
|
|
146
|
+
? `, senderIds: ${JSON.stringify(senderIds)}`
|
|
147
|
+
: ""}${senderNames.length > 0
|
|
148
|
+
? `, senderNames: ${JSON.stringify(senderNames)}`
|
|
149
|
+
: ""}${senders.length > 0 ? `, senders: ${JSON.stringify(senders)}` : ""}${untilDate
|
|
150
|
+
? `, untilDate: "${untilDate}"`
|
|
151
|
+
: `, horizonSendDays: ${horizonSendDays}`}, approvalMode: "${approvalMode}" }) before any import, prep, approval, start, or schedule-affecting action.`,
|
|
152
|
+
"If get_refill_target_plan returns status complete, report gross target, selected days, scheduled count, campaign ids, targetShapeRevision, and no-op proof without asking for approval.",
|
|
153
|
+
"If remainingReadyOrScheduledGap is 0 but remainingScheduledGap is positive, run only a bounded read-only scheduler settle/reread loop; do not ask for prep/import/approval.",
|
|
145
154
|
`Resolve route with resolve_campaign_fill_route({ intent: "${intent}"${input.campaignId ? `, campaignId: "${input.campaignId}"` : ""}${input.tableId ? `, tableId: "${input.tableId}"` : ""} }).`,
|
|
146
155
|
'If the plain route shows stale managed waterfall evidence, archived/completed shared slots, or targets that do not cover the selected sender set, immediately call resolve_campaign_fill_route({ intent: "active" }) and inspect current dashboard-active ACTIVE/PAUSED campaign-backed sequence campaigns before declaring a sender blocked.',
|
|
147
156
|
"Call list_senders and get_sender_routing, then resolve sender selectors against active enrolled campaign-backed sequence senders.",
|
|
@@ -151,15 +160,15 @@ export function refillSendsCommand(input = {}) {
|
|
|
151
160
|
"Read get_campaign_refill_state for enough exact candidate campaigns to pick the best per-sender target by recent/future scheduler-owned sends, then recent result evidence, then source health.",
|
|
152
161
|
"Treat current dashboard-active PAUSED campaign-backed sequence campaigns as start-eligible candidates: read refill state before deciding whether to prep, approve, start, or skip.",
|
|
153
162
|
"Fresh reread get_campaign_refill_state immediately before any import, prep, approval, or horizon-fill mutation.",
|
|
154
|
-
"Maintain a horizon saturation ledger per selected sender: selected
|
|
155
|
-
"In --yolo, continue through every safe selected sender/campaign action covered by the rendered packet;
|
|
163
|
+
"Maintain a target-led horizon saturation ledger per selected sender from get_refill_target_plan: selected days, gross capacity, future scheduler-owned scheduled counts, ready-to-schedule buffer, remaining scheduled gap, remaining ready-or-scheduled gap, targetShapeRevision, stateRevision, and next MCP primitive.",
|
|
164
|
+
"In --yolo or after one Accept, continue through every safe selected sender/campaign action covered by the rendered target packet; scheduled-count progress changes stateRevision and should continue while targetShapeRevision is stable.",
|
|
156
165
|
"Do not complete a fill/schedule request until a final get_campaign_refill_state reread proves scheduler-owned scheduledFor cells fill the horizon, or report a concrete blocker such as awaiting_scheduler_after_ready_buffer.",
|
|
157
166
|
],
|
|
158
167
|
approvalContract: yolo
|
|
159
|
-
? "Auto-accept only the rendered bounded refill packet after fresh reread. Continue through every safe apply/prep/start action inside that packet, including start_campaign only for exact selected PAUSED campaign-backed sequence refill targets named in the packet. After each action,
|
|
168
|
+
? "Auto-accept only the rendered bounded refill target packet after get_refill_target_plan and fresh reread. Continue through every safe apply/prep/start action inside that packet, including start_campaign only for exact selected PAUSED campaign-backed sequence refill targets named in the packet. After each action, rerun get_refill_target_plan; keep going while targetShapeRevision is stable and scheduled counts progress toward the target, even though stateRevision changes. Ready-to-schedule rows are buffer, not completion. If ready buffer covers the gap, use only read-only scheduler settle/reread. Stop immediately if targetShapeRevision changes because sender set, route, ids, caps, dates, blockers, action class, or side-effect class drifts."
|
|
160
169
|
: hasSenderSelectors
|
|
161
|
-
? "Ask the final Accept/Decline structured approval question before mutation
|
|
162
|
-
: "Ask which eligible enrolled senders to refill first, then ask the final Accept/Decline structured approval question before mutation.",
|
|
170
|
+
? "Ask the final Accept/Decline structured approval question before mutation only when get_refill_target_plan reports a positive remaining ready-or-scheduled gap. Include workspace, sender scope, campaign table, exact ids, caps/dates, gross target, scheduled count, ready buffer, remaining scheduled gap, targetShapeRevision/stateRevision, side effects, forbidden actions, and stop condition. If target is complete, no-op without approval. If ready buffer covers the target, run only read-only scheduler settle/reread."
|
|
171
|
+
: "Ask which eligible enrolled senders to refill first, then ask the final Accept/Decline structured approval question before mutation only when get_refill_target_plan reports a positive remaining ready-or-scheduled gap.",
|
|
163
172
|
forbiddenActions: [
|
|
164
173
|
"start_campaign outside an exact selected PAUSED campaign-backed refill packet",
|
|
165
174
|
"manual launch/send or direct sending outside product scheduler side effects",
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
type RefillTargetPlanIntent = "plain" | "active" | "evergreen";
|
|
2
|
+
type RefillTargetPlanApprovalMode = "approve" | "mark_ready";
|
|
3
|
+
type GetRefillTargetPlanInput = {
|
|
4
|
+
intent?: RefillTargetPlanIntent;
|
|
5
|
+
horizonSendDays?: number;
|
|
6
|
+
untilDate?: string;
|
|
7
|
+
campaignId?: string;
|
|
8
|
+
tableId?: string;
|
|
9
|
+
senderIds?: string[];
|
|
10
|
+
senderNames?: string[];
|
|
11
|
+
senders?: string[];
|
|
12
|
+
actionTypes?: string[];
|
|
13
|
+
approvalMode?: RefillTargetPlanApprovalMode;
|
|
14
|
+
};
|
|
15
|
+
export declare const refillTargetPlanToolDefinitions: {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
inputSchema: {
|
|
19
|
+
type: string;
|
|
20
|
+
properties: {
|
|
21
|
+
intent: {
|
|
22
|
+
type: string;
|
|
23
|
+
enum: string[];
|
|
24
|
+
description: string;
|
|
25
|
+
};
|
|
26
|
+
horizonSendDays: {
|
|
27
|
+
type: string;
|
|
28
|
+
minimum: number;
|
|
29
|
+
maximum: number;
|
|
30
|
+
description: string;
|
|
31
|
+
};
|
|
32
|
+
untilDate: {
|
|
33
|
+
type: string;
|
|
34
|
+
pattern: string;
|
|
35
|
+
description: string;
|
|
36
|
+
};
|
|
37
|
+
campaignId: {
|
|
38
|
+
type: string;
|
|
39
|
+
description: string;
|
|
40
|
+
};
|
|
41
|
+
tableId: {
|
|
42
|
+
type: string;
|
|
43
|
+
description: string;
|
|
44
|
+
};
|
|
45
|
+
senderIds: {
|
|
46
|
+
type: string;
|
|
47
|
+
items: {
|
|
48
|
+
type: string;
|
|
49
|
+
};
|
|
50
|
+
description: string;
|
|
51
|
+
};
|
|
52
|
+
senderNames: {
|
|
53
|
+
type: string;
|
|
54
|
+
items: {
|
|
55
|
+
type: string;
|
|
56
|
+
};
|
|
57
|
+
description: string;
|
|
58
|
+
};
|
|
59
|
+
senders: {
|
|
60
|
+
type: string;
|
|
61
|
+
items: {
|
|
62
|
+
type: string;
|
|
63
|
+
};
|
|
64
|
+
description: string;
|
|
65
|
+
};
|
|
66
|
+
actionTypes: {
|
|
67
|
+
type: string;
|
|
68
|
+
items: {
|
|
69
|
+
type: string;
|
|
70
|
+
enum: string[];
|
|
71
|
+
};
|
|
72
|
+
description: string;
|
|
73
|
+
};
|
|
74
|
+
approvalMode: {
|
|
75
|
+
type: string;
|
|
76
|
+
enum: string[];
|
|
77
|
+
description: string;
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
required: never[];
|
|
81
|
+
additionalProperties: boolean;
|
|
82
|
+
};
|
|
83
|
+
}[];
|
|
84
|
+
export declare function getRefillTargetPlan(input?: GetRefillTargetPlanInput): Promise<unknown>;
|
|
85
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { getApi } from "../api.js";
|
|
2
|
+
async function postRefillTargetPlan(body) {
|
|
3
|
+
const api = getApi();
|
|
4
|
+
return api.post("/api/v3/mcp/refill-target-plan", body);
|
|
5
|
+
}
|
|
6
|
+
export const refillTargetPlanToolDefinitions = [
|
|
7
|
+
{
|
|
8
|
+
name: "get_refill_target_plan",
|
|
9
|
+
description: "read-only refill target planner to call before any refill mutation. It computes selected sender-local days, gross scheduled-send target, scheduler-owned scheduled coverage across active enrolled campaigns, ready buffer, remaining scheduled gap, bounded action candidates, and targetRevision drift proof. This tool does not create rows, import leads, prepare messages, approve messages, does not schedule sends, start campaigns, launch, spend InMail credits, or write scheduler fields. Complete targets no-op without approval; incomplete targets must be followed by a bounded approval packet.",
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
intent: {
|
|
14
|
+
type: "string",
|
|
15
|
+
enum: ["plain", "active", "evergreen"],
|
|
16
|
+
description: 'Route intent. Use "plain" for normal refill requests unless the user explicitly narrows active or evergreen.',
|
|
17
|
+
},
|
|
18
|
+
horizonSendDays: {
|
|
19
|
+
type: "number",
|
|
20
|
+
minimum: 1,
|
|
21
|
+
maximum: 7,
|
|
22
|
+
description: "Calendar-day refill horizon to inspect from the sender-local current day. Defaults to 2 when untilDate is not provided; no-send days contribute zero target.",
|
|
23
|
+
},
|
|
24
|
+
untilDate: {
|
|
25
|
+
type: "string",
|
|
26
|
+
pattern: "^\\d{4}-\\d{2}-\\d{2}$",
|
|
27
|
+
description: "Optional sender-local YYYY-MM-DD date to inspect through, inclusive.",
|
|
28
|
+
},
|
|
29
|
+
campaignId: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Optional exact CampaignOffer.id to narrow routing. Do not pass campaign names.",
|
|
32
|
+
},
|
|
33
|
+
tableId: {
|
|
34
|
+
type: "string",
|
|
35
|
+
description: "Optional exact WorkflowTable.id to narrow routing. Do not pass table names.",
|
|
36
|
+
},
|
|
37
|
+
senderIds: {
|
|
38
|
+
type: "array",
|
|
39
|
+
items: { type: "string" },
|
|
40
|
+
description: "Optional exact Sender.id values to scope target planning.",
|
|
41
|
+
},
|
|
42
|
+
senderNames: {
|
|
43
|
+
type: "array",
|
|
44
|
+
items: { type: "string" },
|
|
45
|
+
description: "Optional sender display names to resolve before target planning.",
|
|
46
|
+
},
|
|
47
|
+
senders: {
|
|
48
|
+
type: "array",
|
|
49
|
+
items: { type: "string" },
|
|
50
|
+
description: "Optional sender selectors as names or ids.",
|
|
51
|
+
},
|
|
52
|
+
actionTypes: {
|
|
53
|
+
type: "array",
|
|
54
|
+
items: {
|
|
55
|
+
type: "string",
|
|
56
|
+
enum: [
|
|
57
|
+
"send_invite",
|
|
58
|
+
"send_dm",
|
|
59
|
+
"send_inmail_open",
|
|
60
|
+
"send_inmail_closed",
|
|
61
|
+
"react_and_comment",
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
description: "Optional workflow send column/action types. Defaults from selected active campaign sequences.",
|
|
65
|
+
},
|
|
66
|
+
approvalMode: {
|
|
67
|
+
type: "string",
|
|
68
|
+
enum: ["approve", "mark_ready"],
|
|
69
|
+
description: 'Requested downstream approval mode. Use "approve" only for explicit fill/schedule requests.',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
required: [],
|
|
73
|
+
additionalProperties: false,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
];
|
|
77
|
+
export function getRefillTargetPlan(input = {}) {
|
|
78
|
+
return postRefillTargetPlan({
|
|
79
|
+
intent: input.intent,
|
|
80
|
+
horizonSendDays: input.horizonSendDays,
|
|
81
|
+
untilDate: input.untilDate,
|
|
82
|
+
campaignId: input.campaignId,
|
|
83
|
+
tableId: input.tableId,
|
|
84
|
+
senderIds: input.senderIds,
|
|
85
|
+
senderNames: input.senderNames,
|
|
86
|
+
senders: input.senders,
|
|
87
|
+
actionTypes: input.actionTypes,
|
|
88
|
+
approvalMode: input.approvalMode,
|
|
89
|
+
});
|
|
90
|
+
}
|
package/dist/tools/registry.js
CHANGED
|
@@ -33,6 +33,7 @@ import { onDemandToolDefinitions } from "./one-off.js";
|
|
|
33
33
|
import { processingToolDefinitions } from "./processing.js";
|
|
34
34
|
import { promptToolDefinitions } from "./prompts.js";
|
|
35
35
|
import { readinessToolDefinitions } from "./readiness.js";
|
|
36
|
+
import { refillTargetPlanToolDefinitions } from "./refill-target-plan.js";
|
|
36
37
|
import { refillSendsToolDefinitions } from "./refill-sends.js";
|
|
37
38
|
import { rowToolDefinitions } from "./rows.js";
|
|
38
39
|
import { rubricToolDefinitions } from "./rubrics.js";
|
|
@@ -50,6 +51,7 @@ export const allTools = [
|
|
|
50
51
|
...campaignAbTestToolDefinitions,
|
|
51
52
|
...campaignFillRoutingToolDefinitions,
|
|
52
53
|
...campaignRefillStateToolDefinitions,
|
|
54
|
+
...refillTargetPlanToolDefinitions,
|
|
53
55
|
...refillSendsToolDefinitions,
|
|
54
56
|
...setupEvergreenCampaignsToolDefinitions,
|
|
55
57
|
...campaignHorizonFillToolDefinitions,
|
package/package.json
CHANGED
|
@@ -49,6 +49,7 @@ allowed-tools:
|
|
|
49
49
|
- mcp__sellable__wait_for_campaign_processing
|
|
50
50
|
- mcp__sellable__resolve_campaign_fill_route
|
|
51
51
|
- mcp__sellable__get_campaign_refill_state
|
|
52
|
+
- mcp__sellable__get_refill_target_plan
|
|
52
53
|
- mcp__sellable__fill_campaign_horizon
|
|
53
54
|
- mcp__sellable__start_campaign_message_preparation
|
|
54
55
|
- mcp__sellable__get_campaign_message_preparation_status
|
|
@@ -474,6 +474,19 @@ Transfer rules:
|
|
|
474
474
|
context, and the current offer category. The question should be easy to answer,
|
|
475
475
|
closed-ended, and specific to that prospect. Do not reuse the same generic
|
|
476
476
|
question across every row.
|
|
477
|
+
- Good `{{custom_closed_question}}` examples:
|
|
478
|
+
- `Are you guys trying to make LinkedIn outbound a real founder-led channel, or is it still mostly ad hoc?`
|
|
479
|
+
- `Are you using LinkedIn to reach sales leaders directly, or is most pipeline still coming from intros and email?`
|
|
480
|
+
- `Are you actively testing outbound for growth teams right now, or is LinkedIn still more of a founder-network channel?`
|
|
481
|
+
- `Are you trying to turn customer feedback into account-risk signals, or is that still mostly manual check-ins?`
|
|
482
|
+
- `Are you looking at support conversations as a source of churn risk, or does that still mostly live in tickets and surveys?`
|
|
483
|
+
- `Are you building a repeatable sales motion yet, or is most of it still founder-led experimentation?`
|
|
484
|
+
- `Are you treating LinkedIn as a sales channel this year, or mostly as brand and founder content?`
|
|
485
|
+
- Bad `{{custom_closed_question}}` examples:
|
|
486
|
+
- `Are you trying to avoid manual research + follow-up process?`
|
|
487
|
+
- `Are you interested in seeing Sellable?`
|
|
488
|
+
- `Open to seeing how this would work?`
|
|
489
|
+
- `Do you need more leads, filters, messages, and sequence setup?`
|
|
477
490
|
- The product/category wording in the question should be plain and immediately
|
|
478
491
|
legible, for example `LinkedIn outbound`, `customer success`, `CX operations`,
|
|
479
492
|
`support`, or `post-sales`. Avoid feature-heavy phrasing such as `manual
|
|
@@ -4,6 +4,7 @@ description: Plan regular campaign and evergreen campaign send refill work throu
|
|
|
4
4
|
visibility: public
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- mcp__sellable__refill_sends
|
|
7
|
+
- mcp__sellable__get_refill_target_plan
|
|
7
8
|
- mcp__sellable__get_auth_status
|
|
8
9
|
- mcp__sellable__start_cli_login
|
|
9
10
|
- mcp__sellable__wait_for_cli_login
|
|
@@ -102,11 +103,23 @@ get_subskill_prompt({ subskillName: "refill-sends-workflow" })
|
|
|
102
103
|
```
|
|
103
104
|
|
|
104
105
|
Then follow that workflow exactly. The default path is read-only research:
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
compute the refill target plan first, resolve the route, identify the
|
|
107
|
+
sender-relevant campaign that most recently had scheduler-owned sends, read
|
|
108
|
+
refill state for that target, report the next safe step using campaign names
|
|
109
|
+
first, and stop before mutation unless the user has explicitly approved the
|
|
110
|
+
exact workspace, campaign/table/source ids, caps/dates, approval mode, expected
|
|
111
|
+
side effects, and stop/rollback condition.
|
|
112
|
+
|
|
113
|
+
Immediately after loading the internal workflow, call
|
|
114
|
+
`get_refill_target_plan`. The target plan is the canonical first fact receipt:
|
|
115
|
+
selected sender-local days, gross scheduled-send target, scheduler-owned
|
|
116
|
+
scheduled coverage across active enrolled campaigns, ready buffer, remaining
|
|
117
|
+
scheduled gap, remaining ready-or-scheduled gap, `targetShapeRevision`, and
|
|
118
|
+
`stateRevision`. If the target plan is complete, report that the selected target
|
|
119
|
+
is already filled and no-op without asking for approval. If the ready buffer
|
|
120
|
+
covers the target but scheduled coverage is still short, run only a bounded
|
|
121
|
+
read-only scheduler settle/reread loop and report
|
|
122
|
+
`awaiting_scheduler_after_ready_buffer` if it does not settle.
|
|
110
123
|
|
|
111
124
|
If the plain route's managed waterfall targets are stale, for example skipped
|
|
112
125
|
targets show archived/completed shared slots or the returned targets do not cover
|
|
@@ -147,7 +160,10 @@ packet. It does not authorize starting unrelated, archived, completed, draft, or
|
|
|
147
160
|
direct campaigns, separate launch/send actions, archive or delete cleanup,
|
|
148
161
|
direct scheduler writes, sender reassignment, or campaigns outside those
|
|
149
162
|
selected for the eligible sender set. Stop and re-plan if the route, sender set,
|
|
150
|
-
ids, caps, blockers, or side-effect class drift before mutation.
|
|
163
|
+
ids, caps, blockers, action class, or side-effect class drift before mutation.
|
|
164
|
+
Scheduled counts increasing toward the approved target are expected progress:
|
|
165
|
+
they change `stateRevision`, not `targetShapeRevision`, and do not require a
|
|
166
|
+
second approval.
|
|
151
167
|
|
|
152
168
|
In `--yolo`, continue as far as the rendered packet safely allows. After each
|
|
153
169
|
apply/prep/start result, reread state, settle processing when needed, and move to
|
|
@@ -162,7 +178,8 @@ saturation, not merely prepared/approved/ready rows. Maintain a horizon
|
|
|
162
178
|
saturation ledger per selected sender: selected send days, gross capacity,
|
|
163
179
|
future scheduler-owned scheduled cells with non-null `scheduledFor`,
|
|
164
180
|
ready-to-schedule buffer, remaining scheduled gap, remaining ready-or-scheduled
|
|
165
|
-
gap, and the next MCP primitive that can
|
|
181
|
+
gap, `targetShapeRevision`, `stateRevision`, and the next MCP primitive that can
|
|
182
|
+
reduce the gap. After every
|
|
166
183
|
apply/prep/start result, wait for processing, reread refill state, recompute the
|
|
167
184
|
ledger, then keep applying safe bounded actions until the scheduled count fills
|
|
168
185
|
the horizon or a concrete blocker/timeout is proven. If ready rows cover the
|
|
@@ -3,6 +3,7 @@ name: refill-sends-workflow
|
|
|
3
3
|
description: Internal skill-led refill sends workflow for regular campaigns and evergreen campaigns.
|
|
4
4
|
visibility: internal
|
|
5
5
|
allowed-tools:
|
|
6
|
+
- mcp__sellable__get_refill_target_plan
|
|
6
7
|
- mcp__sellable__list_senders
|
|
7
8
|
- mcp__sellable__get_sender_routing
|
|
8
9
|
- mcp__sellable__get_campaign_waterfall
|
|
@@ -58,7 +59,18 @@ senders", and "load everyone up". A sender-scoped request targets senders
|
|
|
58
59
|
enrolled in active campaign-backed sequence campaigns, not one arbitrary active
|
|
59
60
|
campaign.
|
|
60
61
|
|
|
61
|
-
1. Call `
|
|
62
|
+
1. Call `get_refill_target_plan` first. This read-only target plan is the
|
|
63
|
+
canonical opening receipt: selected sender-local days, gross scheduled-send
|
|
64
|
+
target, scheduler-owned scheduled coverage across active enrolled campaigns,
|
|
65
|
+
ready buffer, remaining scheduled gap, remaining ready-or-scheduled gap,
|
|
66
|
+
bounded action candidates, `targetShapeRevision`, and `stateRevision`.
|
|
67
|
+
If `status:"complete"`, report the target, selected dates, scheduled count,
|
|
68
|
+
campaign ids, and no-op proof without asking for approval or mutating.
|
|
69
|
+
If `remainingReadyOrScheduledGap:0` but `remainingScheduledGap>0`, run only a
|
|
70
|
+
bounded read-only scheduler settle/reread loop; do not ask for
|
|
71
|
+
prep/import/approval. If the scheduler still does not fill, report
|
|
72
|
+
`awaiting_scheduler_after_ready_buffer`.
|
|
73
|
+
2. Call `resolve_campaign_fill_route`. Use `intent:"plain"` for generic
|
|
62
74
|
fill/load language, `intent:"active"` only when the user explicitly narrowed
|
|
63
75
|
to active regular campaigns or when the plain route has stale managed
|
|
64
76
|
waterfall evidence, and `intent:"evergreen"` only when the user explicitly
|
|
@@ -70,7 +82,7 @@ campaign.
|
|
|
70
82
|
and inspect current dashboard-active `ACTIVE` and `PAUSED` campaign-backed
|
|
71
83
|
sequence campaigns before declaring a sender blocked.
|
|
72
84
|
Short form: stale waterfall bindings do not overrule current dashboard-active campaigns.
|
|
73
|
-
|
|
85
|
+
3. Resolve sender context before choosing a target. Call `list_senders`; when a
|
|
74
86
|
managed program is involved, also call `get_campaign_waterfall`, and call
|
|
75
87
|
`get_sender_routing` when territory rules may constrain sender eligibility.
|
|
76
88
|
If the user named senders, map those names to exact sender ids. If the user
|
|
@@ -83,7 +95,7 @@ campaign.
|
|
|
83
95
|
the relevant senders from the most recent scheduler-owned sends in
|
|
84
96
|
refill-state readbacks and report that inference.
|
|
85
97
|
Short form: `--yolo refill senders` means all eligible enrolled senders; non-yolo asks which enrolled senders.
|
|
86
|
-
|
|
98
|
+
4. Read `get_campaign_refill_state` for candidate campaigns from the resolver
|
|
87
99
|
result and from the required active-route refetch when managed waterfall
|
|
88
100
|
evidence looks stale. For a broad `active_campaigns` route, inspect enough
|
|
89
101
|
candidates to identify the campaign or small campaign set that most recently
|
|
@@ -103,9 +115,9 @@ campaign.
|
|
|
103
115
|
already has enough ready/scheduled rows across enrolled campaigns or that a
|
|
104
116
|
different same-sender campaign is needed because the best lane is blocked.
|
|
105
117
|
Short form: `--yolo refill senders` selects all eligible enrolled senders, then the best campaign per sender.
|
|
106
|
-
|
|
118
|
+
5. Pick exact ids from the selected refill-state response. Do not use campaign
|
|
107
119
|
names or table names as target identifiers for tool calls.
|
|
108
|
-
|
|
120
|
+
6. Classify the target from refill state:
|
|
109
121
|
- regular campaign: campaign-backed workflow table with normal source,
|
|
110
122
|
sequence, senders, and send/refill stages.
|
|
111
123
|
- evergreen campaign: managed always-on lane with current source evidence.
|
|
@@ -126,8 +138,8 @@ Use the refill-state response as the current facts receipt:
|
|
|
126
138
|
- horizon saturation ledger per target sender: sender-local send days in scope,
|
|
127
139
|
gross horizon capacity, future scheduler-owned scheduled counts in that
|
|
128
140
|
window, ready-to-schedule buffer, remaining scheduled gap, remaining
|
|
129
|
-
ready-or-scheduled gap, and the next
|
|
130
|
-
the gap;
|
|
141
|
+
ready-or-scheduled gap, `targetShapeRevision`, `stateRevision`, and the next
|
|
142
|
+
smallest MCP primitive that can reduce the gap;
|
|
131
143
|
- row/stage counts: source available, rows, enriched, passed, generated,
|
|
132
144
|
approved, ready to schedule, scheduled;
|
|
133
145
|
- active message prep job;
|
|
@@ -182,15 +194,20 @@ two-day packet.
|
|
|
182
194
|
Short form: default `--yolo refill senders` target is each eligible sender's two-send-day gap.
|
|
183
195
|
|
|
184
196
|
For `--yolo` fill/schedule requests, do not treat "ready" as completion. Build
|
|
185
|
-
and maintain a horizon saturation ledger for every selected sender
|
|
186
|
-
complete only when a final
|
|
187
|
-
scheduler-owned scheduled cells with non-null
|
|
188
|
-
sender's horizon capacity for the selected
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
197
|
+
and maintain a horizon saturation ledger for every selected sender from
|
|
198
|
+
`get_refill_target_plan`. A sender is complete only when a final target-plan or
|
|
199
|
+
refill-state reread proves scheduler-owned scheduled cells with non-null
|
|
200
|
+
`scheduledFor` meet or exceed the sender's horizon capacity for the selected
|
|
201
|
+
send days. Put another way: complete only when a final
|
|
202
|
+
`get_campaign_refill_state` reread proves the scheduler-owned non-null
|
|
203
|
+
`scheduledFor` coverage. Ready-to-schedule rows are only buffer for the product scheduler. If
|
|
204
|
+
ready plus scheduled covers the horizon but scheduled cells do not yet, run a
|
|
205
|
+
bounded read-only scheduler settle loop: wait, reread, recompute the ledger, and
|
|
206
|
+
continue until scheduled coverage is proved or the loop reaches an explicit
|
|
207
|
+
timeout/blocker. Timeout is `awaiting_scheduler_after_ready_buffer`, not
|
|
208
|
+
success, and it does not need a prep/import/approval packet. Short form: ready
|
|
209
|
+
buffer is not success.
|
|
210
|
+
Short form: use a bounded scheduler settle loop before calling it blocked.
|
|
194
211
|
Short form: `--yolo refill senders` completes only on scheduled horizon saturation or a concrete blocker.
|
|
195
212
|
|
|
196
213
|
Rank candidates in this order:
|