@sellable/mcp 0.1.507 → 0.1.509

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.
@@ -10,6 +10,13 @@ const SAFE_PACKET_ACTION_TYPES = new Set([
10
10
  "approve_messages",
11
11
  "start_paused_campaign",
12
12
  "wait_for_scheduler",
13
+ "wait_for_active_work",
14
+ "wait_for_source_import",
15
+ "copy_selected_source_rows",
16
+ "continue_signal_discovery_source",
17
+ "continue_sales_nav_source",
18
+ "continue_prospeo_source",
19
+ "manual_source_replenishment",
13
20
  "refresh_paid_inmail_credits",
14
21
  "lower_paid_inmail_threshold",
15
22
  "switch_to_connection_lane",
@@ -19,6 +26,14 @@ const MANUAL_ONLY_PACKET_ACTION_TYPES = new Set([
19
26
  "lower_paid_inmail_threshold",
20
27
  "switch_to_connection_lane",
21
28
  "create_connection_campaign",
29
+ "continue_sales_nav_source",
30
+ "continue_prospeo_source",
31
+ "manual_source_replenishment",
32
+ ]);
33
+ const TERMINAL_NO_ACTION_BLOCKER_CODES = new Set([
34
+ "paid_inmail_below_threshold",
35
+ "paid_inmail_credit_missing",
36
+ "paid_inmail_credit_stale",
22
37
  ]);
23
38
  const SOURCE_PLAN_STATES = new Set([
24
39
  "not_needed",
@@ -27,6 +42,8 @@ const SOURCE_PLAN_STATES = new Set([
27
42
  "needs_signal_import",
28
43
  "waiting_for_import",
29
44
  "needs_confirm",
45
+ "needs_same_source_copy",
46
+ "needs_provider_continuation",
30
47
  "source_shortfall",
31
48
  "provider_exhausted",
32
49
  "provider_missing",
@@ -156,6 +173,16 @@ function sanitizeActionCandidate(candidate) {
156
173
  tableId: stringValue(candidate.tableId),
157
174
  tableName: stringValue(candidate.tableName) ?? null,
158
175
  columnId: stringValue(candidate.columnId) ?? null,
176
+ sourceLeadListId: stringValue(candidate.sourceLeadListId) ?? null,
177
+ leadSourceProvider: stringValue(candidate.leadSourceProvider) ?? null,
178
+ sourceFingerprint: stringValue(candidate.sourceFingerprint) ?? null,
179
+ sourceInventoryStatus: stringValue(candidate.sourceInventoryStatus) ?? null,
180
+ sourceRowIds: stringArray(candidate.sourceRowIds),
181
+ sourceRowLimit: typeof candidate.sourceRowLimit === "number"
182
+ ? candidate.sourceRowLimit
183
+ : undefined,
184
+ activeJobId: stringValue(candidate.activeJobId) ?? null,
185
+ activeImportStatus: stringValue(candidate.activeImportStatus) ?? null,
159
186
  targetRows: typeof candidate.targetRows === "number" ? candidate.targetRows : undefined,
160
187
  columnRole: stringValue(candidate.columnRole),
161
188
  rowSelector: sanitizeRowSelector(candidate.rowSelector),
@@ -190,9 +217,25 @@ function sanitizeToolInput(value) {
190
217
  return {};
191
218
  return {
192
219
  senderId: stringValue(value.senderId),
220
+ actionType: allowedActionType(value.actionType),
193
221
  campaignId: stringValue(value.campaignId),
194
222
  tableId: stringValue(value.tableId),
195
223
  columnId: stringValue(value.columnId) ?? null,
224
+ sourceLeadListId: stringValue(value.sourceLeadListId) ?? null,
225
+ leadSourceProvider: stringValue(value.leadSourceProvider) ?? null,
226
+ sourceFingerprint: stringValue(value.sourceFingerprint) ?? null,
227
+ activeJobId: stringValue(value.activeJobId) ?? null,
228
+ activeImportStatus: stringValue(value.activeImportStatus) ?? null,
229
+ sourceInventoryStatus: stringValue(value.sourceInventoryStatus) ?? null,
230
+ sourceRowIds: stringArray(value.sourceRowIds),
231
+ sourceRowLimit: typeof value.sourceRowLimit === "number"
232
+ ? value.sourceRowLimit
233
+ : undefined,
234
+ campaignOfferId: stringValue(value.campaignOfferId),
235
+ provider: stringValue(value.provider),
236
+ allowDifferentSourceLeadList: typeof value.allowDifferentSourceLeadList === "boolean"
237
+ ? value.allowDifferentSourceLeadList
238
+ : undefined,
196
239
  targetPreparedMessages: typeof value.targetPreparedMessages === "number"
197
240
  ? value.targetPreparedMessages
198
241
  : undefined,
@@ -219,6 +262,10 @@ function sanitizePacketIds(value) {
219
262
  campaignId: stringValue(value.campaignId),
220
263
  tableId: stringValue(value.tableId),
221
264
  columnId: stringValue(value.columnId) ?? null,
265
+ sourceLeadListId: stringValue(value.sourceLeadListId) ?? null,
266
+ leadSourceProvider: stringValue(value.leadSourceProvider) ?? null,
267
+ sourceFingerprint: stringValue(value.sourceFingerprint) ?? null,
268
+ activeJobId: stringValue(value.activeJobId) ?? null,
222
269
  };
223
270
  }
224
271
  function sanitizeStructuredAction(action, selectedBySender, mode, rank) {
@@ -241,6 +288,7 @@ function sanitizeStructuredAction(action, selectedBySender, mode, rank) {
241
288
  return {
242
289
  rank,
243
290
  type: action.type,
291
+ actionType: allowedActionType(action.actionType),
244
292
  toolName: stringValue(action.toolName) ?? null,
245
293
  sideEffectClass: stringValue(action.sideEffectClass),
246
294
  ids,
@@ -338,6 +386,9 @@ function sanitizeSourcePlan(value) {
338
386
  reason: stringValue(value.reason),
339
387
  campaignId: stringValue(value.campaignId),
340
388
  tableId: stringValue(value.tableId),
389
+ sourceLeadListId: stringValue(value.sourceLeadListId) ?? null,
390
+ leadSourceProvider: stringValue(value.leadSourceProvider) ?? null,
391
+ sourceFingerprint: stringValue(value.sourceFingerprint) ?? null,
341
392
  remainingRowsNeeded: typeof value.remainingRowsNeeded === "number"
342
393
  ? value.remainingRowsNeeded
343
394
  : undefined,
@@ -586,14 +637,16 @@ function sanitizeRefillTargetPlanResult(result) {
586
637
  const eligibleSenderLedger = sanitizeEligibleSenderLedger(target.eligibleSenderLedger, selectedBySender);
587
638
  const senderRefillPlans = sanitizeStructuredSenderPlans(target.senderRefillPlans, selectedBySender);
588
639
  const globalActionQueue = buildSanitizedGlobalActionQueue(senderRefillPlans);
589
- const status = blockers.some((blocker) => ["sender_disconnected", "sender_sales_nav_disconnected"].includes(String(blocker.code)))
590
- ? "blocked"
591
- : remainingProjectedGap === 0
592
- ? "complete"
593
- : grossTarget <= 0
594
- ? "blocked"
595
- : remainingReadyOrProjectedGap === 0
596
- ? "awaiting_scheduler_after_ready_buffer"
640
+ const hasTerminalNoActionBlocker = globalActionQueue.length === 0 &&
641
+ blockers.some((blocker) => TERMINAL_NO_ACTION_BLOCKER_CODES.has(String(blocker.code)));
642
+ const status = remainingProjectedGap === 0
643
+ ? "complete"
644
+ : grossTarget <= 0
645
+ ? "blocked"
646
+ : remainingReadyOrProjectedGap === 0
647
+ ? "awaiting_scheduler_after_ready_buffer"
648
+ : hasTerminalNoActionBlocker
649
+ ? "blocked"
597
650
  : "needs_refill";
598
651
  return {
599
652
  ...result,
@@ -584,89 +584,6 @@ export declare const allTools: ({
584
584
  required: string[];
585
585
  additionalProperties: boolean;
586
586
  };
587
- } | {
588
- name: string;
589
- description: string;
590
- inputSchema: {
591
- type: string;
592
- properties: {
593
- campaignId: {
594
- type: string;
595
- description: string;
596
- };
597
- tableId: {
598
- type: string;
599
- };
600
- targetPreparedMessages: {
601
- type: string;
602
- minimum: number;
603
- maximum: number;
604
- };
605
- maxRowsToCheck: {
606
- type: string;
607
- minimum: number;
608
- maximum: number;
609
- description: string;
610
- };
611
- batchSize: {
612
- type: string;
613
- minimum: number;
614
- maximum: number;
615
- description: string;
616
- };
617
- maxBatchRows: {
618
- type: string;
619
- minimum: number;
620
- maximum: number;
621
- description: string;
622
- };
623
- approvalMode: {
624
- type: string;
625
- enum: string[];
626
- description: string;
627
- };
628
- autoContinue: {
629
- type: string;
630
- };
631
- disableLowPassRateStop: {
632
- type: string;
633
- description: string;
634
- };
635
- rowSelector: {
636
- type: string;
637
- description: string;
638
- properties: {
639
- type: {
640
- type: string;
641
- enum: string[];
642
- };
643
- basisHash: {
644
- type: string;
645
- };
646
- rowIds: {
647
- type: string;
648
- items: {
649
- type: string;
650
- };
651
- };
652
- limit: {
653
- type: string;
654
- minimum: number;
655
- maximum: number;
656
- };
657
- };
658
- required: string[];
659
- additionalProperties: boolean;
660
- };
661
- workspaceId: {
662
- type: string;
663
- description: string;
664
- };
665
- jobId?: undefined;
666
- };
667
- required: string[];
668
- additionalProperties: boolean;
669
- };
670
587
  } | {
671
588
  name: string;
672
589
  description: string;
@@ -692,9 +609,11 @@ export declare const allTools: ({
692
609
  batchSize?: undefined;
693
610
  maxBatchRows?: undefined;
694
611
  approvalMode?: undefined;
612
+ rowSelector?: undefined;
695
613
  autoContinue?: undefined;
614
+ senderId?: undefined;
615
+ actionType?: undefined;
696
616
  disableLowPassRateStop?: undefined;
697
- rowSelector?: undefined;
698
617
  };
699
618
  additionalProperties: boolean;
700
619
  required?: undefined;
@@ -1160,6 +1079,7 @@ export declare const allTools: ({
1160
1079
  useMessagingTemplate?: undefined;
1161
1080
  rubric?: undefined;
1162
1081
  flowVersion?: undefined;
1082
+ workspaceId?: undefined;
1163
1083
  };
1164
1084
  required: string[];
1165
1085
  additionalProperties: boolean;
@@ -1198,6 +1118,7 @@ export declare const allTools: ({
1198
1118
  useMessagingTemplate?: undefined;
1199
1119
  rubric?: undefined;
1200
1120
  flowVersion?: undefined;
1121
+ workspaceId?: undefined;
1201
1122
  };
1202
1123
  required: never[];
1203
1124
  additionalProperties?: undefined;
@@ -1236,6 +1157,7 @@ export declare const allTools: ({
1236
1157
  useMessagingTemplate?: undefined;
1237
1158
  rubric?: undefined;
1238
1159
  flowVersion?: undefined;
1160
+ workspaceId?: undefined;
1239
1161
  };
1240
1162
  required: string[];
1241
1163
  additionalProperties?: undefined;
@@ -1317,6 +1239,7 @@ export declare const allTools: ({
1317
1239
  useMessagingTemplate?: undefined;
1318
1240
  rubric?: undefined;
1319
1241
  flowVersion?: undefined;
1242
+ workspaceId?: undefined;
1320
1243
  };
1321
1244
  required: string[];
1322
1245
  additionalProperties: boolean;
@@ -1511,6 +1434,7 @@ export declare const allTools: ({
1511
1434
  useMessagingTemplate?: undefined;
1512
1435
  rubric?: undefined;
1513
1436
  flowVersion?: undefined;
1437
+ workspaceId?: undefined;
1514
1438
  };
1515
1439
  required: never[];
1516
1440
  additionalProperties?: undefined;
@@ -1716,6 +1640,49 @@ export declare const allTools: ({
1716
1640
  clientProspectId?: undefined;
1717
1641
  senderLinkedinUrl?: undefined;
1718
1642
  messageGenerationMode?: undefined;
1643
+ workspaceId?: undefined;
1644
+ };
1645
+ required: string[];
1646
+ additionalProperties?: undefined;
1647
+ };
1648
+ } | {
1649
+ name: string;
1650
+ description: string;
1651
+ inputSchema: {
1652
+ type: string;
1653
+ properties: {
1654
+ campaignId: {
1655
+ type: string;
1656
+ description: string;
1657
+ };
1658
+ workspaceId: {
1659
+ type: string;
1660
+ description: string;
1661
+ };
1662
+ limit?: undefined;
1663
+ tableId?: undefined;
1664
+ leadLimit?: undefined;
1665
+ page?: undefined;
1666
+ filters?: undefined;
1667
+ name?: undefined;
1668
+ clientProspectId?: undefined;
1669
+ senderLinkedinUrl?: undefined;
1670
+ offerPositioning?: undefined;
1671
+ campaignBrief?: undefined;
1672
+ messageGenerationMode?: undefined;
1673
+ currentStep?: undefined;
1674
+ watchNarration?: undefined;
1675
+ leadSourceType?: undefined;
1676
+ leadSourceProvider?: undefined;
1677
+ selectedLeadListId?: undefined;
1678
+ senderIds?: undefined;
1679
+ currentStepTransition?: undefined;
1680
+ clearCurrentStepIfMatches?: undefined;
1681
+ interactionMode?: undefined;
1682
+ enableICPFilters?: undefined;
1683
+ useMessagingTemplate?: undefined;
1684
+ rubric?: undefined;
1685
+ flowVersion?: undefined;
1719
1686
  };
1720
1687
  required: string[];
1721
1688
  additionalProperties?: undefined;
@@ -1757,6 +1724,7 @@ export declare const allTools: ({
1757
1724
  useMessagingTemplate?: undefined;
1758
1725
  rubric?: undefined;
1759
1726
  flowVersion?: undefined;
1727
+ workspaceId?: undefined;
1760
1728
  };
1761
1729
  required: string[];
1762
1730
  additionalProperties?: undefined;
@@ -3131,6 +3099,8 @@ export declare const allTools: ({
3131
3099
  keepInSync?: undefined;
3132
3100
  jobId?: undefined;
3133
3101
  reviewBatchLimit?: undefined;
3102
+ sourceRowIds?: undefined;
3103
+ sourceRowLimit?: undefined;
3134
3104
  allowPartialSourceList?: undefined;
3135
3105
  includeRawImportResult?: undefined;
3136
3106
  selections?: undefined;
@@ -3325,6 +3295,8 @@ export declare const allTools: ({
3325
3295
  keepInSync?: undefined;
3326
3296
  jobId?: undefined;
3327
3297
  reviewBatchLimit?: undefined;
3298
+ sourceRowIds?: undefined;
3299
+ sourceRowLimit?: undefined;
3328
3300
  allowPartialSourceList?: undefined;
3329
3301
  includeRawImportResult?: undefined;
3330
3302
  selections?: undefined;
@@ -3418,6 +3390,8 @@ export declare const allTools: ({
3418
3390
  keepInSync?: undefined;
3419
3391
  jobId?: undefined;
3420
3392
  reviewBatchLimit?: undefined;
3393
+ sourceRowIds?: undefined;
3394
+ sourceRowLimit?: undefined;
3421
3395
  allowPartialSourceList?: undefined;
3422
3396
  includeRawImportResult?: undefined;
3423
3397
  selections?: undefined;
@@ -3583,6 +3557,8 @@ export declare const allTools: ({
3583
3557
  keepInSync?: undefined;
3584
3558
  jobId?: undefined;
3585
3559
  reviewBatchLimit?: undefined;
3560
+ sourceRowIds?: undefined;
3561
+ sourceRowLimit?: undefined;
3586
3562
  allowPartialSourceList?: undefined;
3587
3563
  includeRawImportResult?: undefined;
3588
3564
  selections?: undefined;
@@ -3690,6 +3666,8 @@ export declare const allTools: ({
3690
3666
  keepInSync?: undefined;
3691
3667
  jobId?: undefined;
3692
3668
  reviewBatchLimit?: undefined;
3669
+ sourceRowIds?: undefined;
3670
+ sourceRowLimit?: undefined;
3693
3671
  allowPartialSourceList?: undefined;
3694
3672
  includeRawImportResult?: undefined;
3695
3673
  selections?: undefined;
@@ -3806,6 +3784,8 @@ export declare const allTools: ({
3806
3784
  keepInSync?: undefined;
3807
3785
  jobId?: undefined;
3808
3786
  reviewBatchLimit?: undefined;
3787
+ sourceRowIds?: undefined;
3788
+ sourceRowLimit?: undefined;
3809
3789
  allowPartialSourceList?: undefined;
3810
3790
  includeRawImportResult?: undefined;
3811
3791
  selections?: undefined;
@@ -3911,6 +3891,8 @@ export declare const allTools: ({
3911
3891
  keepInSync?: undefined;
3912
3892
  jobId?: undefined;
3913
3893
  reviewBatchLimit?: undefined;
3894
+ sourceRowIds?: undefined;
3895
+ sourceRowLimit?: undefined;
3914
3896
  allowPartialSourceList?: undefined;
3915
3897
  includeRawImportResult?: undefined;
3916
3898
  selections?: undefined;
@@ -4021,6 +4003,8 @@ export declare const allTools: ({
4021
4003
  keepInSync?: undefined;
4022
4004
  jobId?: undefined;
4023
4005
  reviewBatchLimit?: undefined;
4006
+ sourceRowIds?: undefined;
4007
+ sourceRowLimit?: undefined;
4024
4008
  allowPartialSourceList?: undefined;
4025
4009
  includeRawImportResult?: undefined;
4026
4010
  selections?: undefined;
@@ -4119,6 +4103,8 @@ export declare const allTools: ({
4119
4103
  keepInSync?: undefined;
4120
4104
  jobId?: undefined;
4121
4105
  reviewBatchLimit?: undefined;
4106
+ sourceRowIds?: undefined;
4107
+ sourceRowLimit?: undefined;
4122
4108
  allowPartialSourceList?: undefined;
4123
4109
  includeRawImportResult?: undefined;
4124
4110
  selections?: undefined;
@@ -5009,6 +4995,8 @@ export declare const allTools: ({
5009
4995
  keepInSync?: undefined;
5010
4996
  jobId?: undefined;
5011
4997
  reviewBatchLimit?: undefined;
4998
+ sourceRowIds?: undefined;
4999
+ sourceRowLimit?: undefined;
5012
5000
  allowPartialSourceList?: undefined;
5013
5001
  includeRawImportResult?: undefined;
5014
5002
  selections?: undefined;
@@ -5116,6 +5104,8 @@ export declare const allTools: ({
5116
5104
  keepInSync?: undefined;
5117
5105
  jobId?: undefined;
5118
5106
  reviewBatchLimit?: undefined;
5107
+ sourceRowIds?: undefined;
5108
+ sourceRowLimit?: undefined;
5119
5109
  allowPartialSourceList?: undefined;
5120
5110
  includeRawImportResult?: undefined;
5121
5111
  selections?: undefined;
@@ -6161,6 +6151,8 @@ export declare const allTools: ({
6161
6151
  keepInSync?: undefined;
6162
6152
  jobId?: undefined;
6163
6153
  reviewBatchLimit?: undefined;
6154
+ sourceRowIds?: undefined;
6155
+ sourceRowLimit?: undefined;
6164
6156
  allowPartialSourceList?: undefined;
6165
6157
  includeRawImportResult?: undefined;
6166
6158
  selections?: undefined;
@@ -6315,6 +6307,8 @@ export declare const allTools: ({
6315
6307
  keepInSync?: undefined;
6316
6308
  jobId?: undefined;
6317
6309
  reviewBatchLimit?: undefined;
6310
+ sourceRowIds?: undefined;
6311
+ sourceRowLimit?: undefined;
6318
6312
  allowPartialSourceList?: undefined;
6319
6313
  includeRawImportResult?: undefined;
6320
6314
  selections?: undefined;
@@ -6456,6 +6450,8 @@ export declare const allTools: ({
6456
6450
  keepInSync?: undefined;
6457
6451
  jobId?: undefined;
6458
6452
  reviewBatchLimit?: undefined;
6453
+ sourceRowIds?: undefined;
6454
+ sourceRowLimit?: undefined;
6459
6455
  allowPartialSourceList?: undefined;
6460
6456
  includeRawImportResult?: undefined;
6461
6457
  selections?: undefined;
@@ -6552,6 +6548,8 @@ export declare const allTools: ({
6552
6548
  keepInSync?: undefined;
6553
6549
  jobId?: undefined;
6554
6550
  reviewBatchLimit?: undefined;
6551
+ sourceRowIds?: undefined;
6552
+ sourceRowLimit?: undefined;
6555
6553
  allowPartialSourceList?: undefined;
6556
6554
  includeRawImportResult?: undefined;
6557
6555
  selections?: undefined;
@@ -6598,6 +6596,17 @@ export declare const allTools: ({
6598
6596
  type: string;
6599
6597
  description: string;
6600
6598
  };
6599
+ sourceRowIds: {
6600
+ type: string;
6601
+ items: {
6602
+ type: string;
6603
+ };
6604
+ description: string;
6605
+ };
6606
+ sourceRowLimit: {
6607
+ type: string;
6608
+ description: string;
6609
+ };
6601
6610
  allowPartialSourceList: {
6602
6611
  type: string;
6603
6612
  description: string;
@@ -6807,6 +6816,8 @@ export declare const allTools: ({
6807
6816
  keepInSync?: undefined;
6808
6817
  jobId?: undefined;
6809
6818
  reviewBatchLimit?: undefined;
6819
+ sourceRowIds?: undefined;
6820
+ sourceRowLimit?: undefined;
6810
6821
  allowPartialSourceList?: undefined;
6811
6822
  includeRawImportResult?: undefined;
6812
6823
  };
@@ -6904,6 +6915,8 @@ export declare const allTools: ({
6904
6915
  keepInSync?: undefined;
6905
6916
  jobId?: undefined;
6906
6917
  reviewBatchLimit?: undefined;
6918
+ sourceRowIds?: undefined;
6919
+ sourceRowLimit?: undefined;
6907
6920
  allowPartialSourceList?: undefined;
6908
6921
  includeRawImportResult?: undefined;
6909
6922
  selections?: undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.507",
3
+ "version": "0.1.509",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code and Codex campaign workflows",
6
6
  "main": "dist/index.js",
@@ -92,10 +92,16 @@ When the host can call typed MCP tools, start with:
92
92
  refill_sends({ yolo?: boolean, executionMode?: "manual" | "scheduled" | "yolo", requireWorkspace?: boolean, workspaceId?: string, senders?: string[], senderIds?: string[], senderNames?: string[], horizonSendDays?: number, untilDate?: "YYYY-MM-DD", targetDate?: "YYYY-MM-DD" })
93
93
  ```
94
94
 
95
- That command helper only normalizes arguments and returns the execution
96
- contract. It does not mutate. Continue with the workflow below for route
97
- selection, state rereads, approval gating, source import, preparation, and
98
- bounded approval.
95
+ That command helper normalizes arguments and returns the execution contract. In
96
+ non-yolo mode it does not mutate. In `--yolo`, it may execute exactly one safe
97
+ bounded primitive from the fresh `target.globalActionQueue[0]`, then reread and
98
+ return the new target plan; currently safe primitives are paid-credit refresh,
99
+ existing-row message preparation, same-source row copy, and read-only wait
100
+ rereads. It does not run unbounded approval, lower
101
+ paid-InMail thresholds, switch source families, create campaigns, launch, send,
102
+ or write scheduler rows. Continue with the workflow below for route selection,
103
+ state rereads, approval gating, source import, preparation, and bounded
104
+ approval.
99
105
 
100
106
  ## Workspace Contract
101
107
 
@@ -199,12 +205,20 @@ Structured planner packet:
199
205
  - `manualAlternates` are not yolo actions. Threshold lowering and campaign
200
206
  creation are manual continuations only.
201
207
 
208
+ Refill action ladder: approve generated rows only when an explicit bounded
209
+ approval gate exists, process all existing same-campaign unenriched/unprepared
210
+ rows in bounded batches before any source work, then copy bounded net-new rows
211
+ from the selected source (`selectedLeadListId`, provider, and source
212
+ fingerprint preserved), then use provider-aligned source-more. A new source or
213
+ provider switch changes the reply-rate baseline and is a manual alternate, not a
214
+ `--yolo` side effect.
215
+
202
216
  Run-local paid-credit guard: in `--yolo`, the `refill_sends` MCP command
203
217
  automatically maintains a `refreshedPaidInmailSenderIds` set for the current
204
218
  command call. If its first target plan has stale/missing paid-InMail credit
205
219
  facts, it refreshes each selected sender at most once, reruns
206
220
  `get_refill_target_plan`, and returns the post-refresh `targetPlan` before
207
- choosing the next prep/approval/start action. If fresh facts are still below
221
+ choosing the next prep/source-copy/bounded-approval/read-only wait action. If fresh facts are still below
208
222
  threshold, below-threshold paid-InMail facts fall back to an existing connection
209
223
  lane, the same Sales Nav cascade campaign's connection branch, or a manual
210
224
  continuation.
@@ -238,10 +252,7 @@ next action in `--yolo`. Do not present paid-credit refresh as the next operator
238
252
  action after `refill_sends` returns `autoPaidInmailRefresh` and the
239
253
  post-refresh `targetPlan`. Trust `refill_sends.autoPaidInmailRefresh`: it should
240
254
  show the exact sender ids refreshed once, sender-credit-cache write receipts,
241
- and a returned post-refresh `targetPlan`. Also inspect
242
- `refill_sends.yoloExecution`: if it applied a supported yolo action, continue
243
- from the final returned `targetPlan`; otherwise continue from the post-refresh
244
- packet or `targetPlanBeforeYoloAction`.
255
+ and a returned post-refresh `targetPlan`. Continue from that post-refresh packet.
245
256
  If paid InMail is below threshold after the fresh credit read, report the exact
246
257
  campaign/table/column threshold action or same-campaign connection fallback;
247
258
  `--yolo` does not lower paid-InMail thresholds or create campaigns.
@@ -296,7 +307,7 @@ they change `stateRevision`, not `targetShapeRevision`, and do not require a
296
307
  second approval.
297
308
 
298
309
  In `--yolo`, continue as far as the rendered packet safely allows. After each
299
- apply/prep/start result, reread state, settle processing when needed, and move to
310
+ apply/prep/source-copy/bounded-approval/read-only wait result, reread state, settle processing when needed, and move to
300
311
  the next selected sender or start-eligible same-packet campaign instead of
301
312
  stopping after the first partial result. If no in-packet safe action remains,
302
313
  return concrete continuation options with campaign names, exact ids, which option
@@ -310,7 +321,7 @@ selected sender: selected send days, gross capacity, actual sent cells, future
310
321
  scheduler-owned scheduled cells with non-null `scheduledFor`, projected count,
311
322
  ready-to-schedule buffer, remaining projected gap, paid-InMail feasibility,
312
323
  `targetShapeRevision`, `stateRevision`, and the next MCP primitive that can
313
- reduce the gap. After every apply/prep/start result, wait for processing, reread
324
+ reduce the gap. After every apply/prep/source-copy/bounded-approval/read-only wait result, wait for processing, reread
314
325
  the target plan/refill state, recompute the ledger, then keep applying safe
315
326
  bounded actions until projected coverage fills the target window or a concrete
316
327
  non-scheduler blocker is proven.
@@ -120,12 +120,19 @@ in-progress wait state, not a reason to mark the goal complete or blocked.
120
120
  - `nextActions[0]` is the current sender's smallest safe primitive.
121
121
  - `manualAlternates` are not yolo actions. Threshold lowering and campaign
122
122
  creation are manual continuations only.
123
+ Refill action ladder: approve generated rows only when an explicit bounded
124
+ approval gate exists, process all existing same-campaign
125
+ unenriched/unprepared rows in bounded batches before any source work, then
126
+ copy bounded net-new rows from the selected source (`selectedLeadListId`,
127
+ provider, and source fingerprint preserved), then use provider-aligned
128
+ source-more. A new source or provider switch changes the reply-rate baseline
129
+ and is a manual alternate, not a `--yolo` side effect.
123
130
  Run-local paid-credit guard: in `--yolo`, the `refill_sends` MCP command
124
131
  automatically maintains a `refreshedPaidInmailSenderIds` set for the current
125
132
  command call. If its first target plan has stale/missing paid-InMail credit
126
133
  facts, it refreshes each selected sender at most once, reruns
127
134
  `get_refill_target_plan`, and returns the post-refresh `targetPlan` before
128
- choosing the next prep/approval/start action. If fresh facts are still below
135
+ choosing the next prep/source-copy/bounded-approval/read-only wait action. If fresh facts are still below
129
136
  threshold, below-threshold paid-InMail facts fall back to an existing
130
137
  connection lane, the same Sales Nav cascade campaign's connection branch, or
131
138
  a manual continuation.
@@ -161,10 +168,8 @@ in-progress wait state, not a reason to mark the goal complete or blocked.
161
168
  operator action after `refill_sends` returns `autoPaidInmailRefresh` and the
162
169
  post-refresh `targetPlan`. Trust `refill_sends.autoPaidInmailRefresh`: it
163
170
  should show the exact sender ids refreshed once, sender-credit-cache write
164
- receipts, and a returned post-refresh `targetPlan`. Also inspect
165
- `refill_sends.yoloExecution`: if it applied a supported yolo action,
166
- continue from the final returned `targetPlan`; otherwise continue from the
167
- post-refresh packet or `targetPlanBeforeYoloAction`. If paid InMail is below threshold after the fresh credit read, report
171
+ receipts, and a returned post-refresh `targetPlan`. Continue from that
172
+ post-refresh packet. If paid InMail is below threshold after the fresh credit read, report
168
173
  the exact campaign/table/column threshold action or same-campaign
169
174
  connection fallback; `--yolo` does not lower paid-InMail thresholds or create campaigns.
170
175
  2. Call `resolve_campaign_fill_route`. Use `intent:"plain"` for generic
@@ -566,7 +571,7 @@ same refill request, do not ask the `Accept` / `Decline` question. Instead:
566
571
  caps/dates, approval mode, blockers, and side-effect class still match the
567
572
  packet;
568
573
  4. execute only the exact packet;
569
- 5. after each terminal credit-refresh/apply/prep/start result, rerun
574
+ 5. after each terminal credit-refresh/apply/prep/source-copy/bounded-approval/read-only wait result, rerun
570
575
  `get_refill_target_plan`, reread state, settle processing when needed,
571
576
  recompute the target-window saturation ledger, and continue with the next smallest
572
577
  safe action inside the same bounded packet until every selected sender is