@sellable/mcp 0.1.540 → 0.1.542

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.
Files changed (39) hide show
  1. package/README.md +2 -5
  2. package/dist/index-dev.js +0 -0
  3. package/dist/index.js +0 -0
  4. package/dist/refill-run-loop.d.ts +1 -9
  5. package/dist/refill-run-loop.js +91 -156
  6. package/dist/server.js +5 -1
  7. package/dist/tools/campaigns.d.ts +50 -1
  8. package/dist/tools/campaigns.js +6 -2
  9. package/dist/tools/evergreen-refill-plan.d.ts +0 -19
  10. package/dist/tools/evergreen-refill-plan.js +0 -19
  11. package/dist/tools/refill-executors.d.ts +7 -0
  12. package/dist/tools/refill-executors.js +23 -1
  13. package/dist/tools/refill-sends-v2.d.ts +0 -19
  14. package/dist/tools/refill-sends-v2.js +2 -31
  15. package/dist/tools/refill-sends.d.ts +12 -0
  16. package/dist/tools/refill-sends.js +58 -36
  17. package/dist/tools/refill-target-plan.js +6 -19
  18. package/dist/tools/refresh-sender-engagement.d.ts +50 -0
  19. package/dist/tools/refresh-sender-engagement.js +60 -0
  20. package/dist/tools/registry.d.ts +88 -32
  21. package/dist/tools/registry.js +2 -0
  22. package/dist/tools/scheduler-fill-capacity.js +1 -1
  23. package/dist/tools/scheduler-run.d.ts +1 -1
  24. package/dist/tools/scheduler-run.js +17 -20
  25. package/dist/tools/senders.d.ts +14 -8
  26. package/dist/tools/senders.js +21 -10
  27. package/package.json +1 -1
  28. package/skills/refill-sends/SKILL.md +1 -9
  29. package/skills/refill-sends-v2/SKILL.md +5 -18
  30. package/skills/refill-sends-v2-workflow/SKILL.md +2 -16
  31. package/skills/refill-sends-v2-workflow/core/flow.v1.json +3 -19
  32. package/skills/refill-sends-workflow/SKILL.md +3 -5
  33. package/skills/refill-sends-workflow/core/flow.v1.json +1 -1
  34. package/skills/refresh-sender-engagement/SKILL.md +25 -29
  35. package/dist/refill-date-window.d.ts +0 -34
  36. package/dist/refill-date-window.js +0 -210
  37. package/dist/tools/refill-sends-evergreen.d.ts +0 -28
  38. package/dist/tools/refill-sends-evergreen.js +0 -47
  39. package/skills/research/config.json +0 -9
@@ -1118,6 +1118,7 @@ export declare const allTools: ({
1118
1118
  useMessagingTemplate?: undefined;
1119
1119
  rubric?: undefined;
1120
1120
  flowVersion?: undefined;
1121
+ workspaceId?: undefined;
1121
1122
  };
1122
1123
  required: string[];
1123
1124
  additionalProperties: boolean;
@@ -1156,6 +1157,7 @@ export declare const allTools: ({
1156
1157
  useMessagingTemplate?: undefined;
1157
1158
  rubric?: undefined;
1158
1159
  flowVersion?: undefined;
1160
+ workspaceId?: undefined;
1159
1161
  };
1160
1162
  required: never[];
1161
1163
  additionalProperties?: undefined;
@@ -1194,6 +1196,7 @@ export declare const allTools: ({
1194
1196
  useMessagingTemplate?: undefined;
1195
1197
  rubric?: undefined;
1196
1198
  flowVersion?: undefined;
1199
+ workspaceId?: undefined;
1197
1200
  };
1198
1201
  required: string[];
1199
1202
  additionalProperties?: undefined;
@@ -1275,6 +1278,7 @@ export declare const allTools: ({
1275
1278
  useMessagingTemplate?: undefined;
1276
1279
  rubric?: undefined;
1277
1280
  flowVersion?: undefined;
1281
+ workspaceId?: undefined;
1278
1282
  };
1279
1283
  required: string[];
1280
1284
  additionalProperties: boolean;
@@ -1469,6 +1473,7 @@ export declare const allTools: ({
1469
1473
  useMessagingTemplate?: undefined;
1470
1474
  rubric?: undefined;
1471
1475
  flowVersion?: undefined;
1476
+ workspaceId?: undefined;
1472
1477
  };
1473
1478
  required: never[];
1474
1479
  additionalProperties?: undefined;
@@ -1674,6 +1679,49 @@ export declare const allTools: ({
1674
1679
  clientProspectId?: undefined;
1675
1680
  senderLinkedinUrl?: undefined;
1676
1681
  messageGenerationMode?: undefined;
1682
+ workspaceId?: undefined;
1683
+ };
1684
+ required: string[];
1685
+ additionalProperties?: undefined;
1686
+ };
1687
+ } | {
1688
+ name: string;
1689
+ description: string;
1690
+ inputSchema: {
1691
+ type: string;
1692
+ properties: {
1693
+ campaignId: {
1694
+ type: string;
1695
+ description: string;
1696
+ };
1697
+ workspaceId: {
1698
+ type: string;
1699
+ description: string;
1700
+ };
1701
+ limit?: undefined;
1702
+ tableId?: undefined;
1703
+ leadLimit?: undefined;
1704
+ page?: undefined;
1705
+ filters?: undefined;
1706
+ name?: undefined;
1707
+ clientProspectId?: undefined;
1708
+ senderLinkedinUrl?: undefined;
1709
+ offerPositioning?: undefined;
1710
+ campaignBrief?: undefined;
1711
+ messageGenerationMode?: undefined;
1712
+ currentStep?: undefined;
1713
+ watchNarration?: undefined;
1714
+ leadSourceType?: undefined;
1715
+ leadSourceProvider?: undefined;
1716
+ selectedLeadListId?: undefined;
1717
+ senderIds?: undefined;
1718
+ currentStepTransition?: undefined;
1719
+ clearCurrentStepIfMatches?: undefined;
1720
+ interactionMode?: undefined;
1721
+ enableICPFilters?: undefined;
1722
+ useMessagingTemplate?: undefined;
1723
+ rubric?: undefined;
1724
+ flowVersion?: undefined;
1677
1725
  };
1678
1726
  required: string[];
1679
1727
  additionalProperties?: undefined;
@@ -1715,6 +1763,7 @@ export declare const allTools: ({
1715
1763
  useMessagingTemplate?: undefined;
1716
1764
  rubric?: undefined;
1717
1765
  flowVersion?: undefined;
1766
+ workspaceId?: undefined;
1718
1767
  };
1719
1768
  required: string[];
1720
1769
  additionalProperties?: undefined;
@@ -2758,22 +2807,6 @@ export declare const allTools: ({
2758
2807
  enum: string[];
2759
2808
  description: string;
2760
2809
  };
2761
- targetDate: {
2762
- type: string;
2763
- pattern: string;
2764
- description: string;
2765
- };
2766
- untilDate: {
2767
- type: string;
2768
- pattern: string;
2769
- description: string;
2770
- };
2771
- horizonSendDays: {
2772
- type: string;
2773
- minimum: number;
2774
- maximum: number;
2775
- description: string;
2776
- };
2777
2810
  journal: {
2778
2811
  type: string;
2779
2812
  description: string;
@@ -7386,6 +7419,45 @@ export declare const allTools: ({
7386
7419
  };
7387
7420
  required: string[];
7388
7421
  };
7422
+ } | {
7423
+ name: string;
7424
+ description: string;
7425
+ inputSchema: {
7426
+ type: string;
7427
+ properties: {
7428
+ workspaceId: {
7429
+ type: string;
7430
+ description: string;
7431
+ };
7432
+ mode: {
7433
+ type: string;
7434
+ enum: string[];
7435
+ description: string;
7436
+ };
7437
+ senderId: {
7438
+ type: string;
7439
+ description: string;
7440
+ };
7441
+ tableId: {
7442
+ type: string;
7443
+ description: string;
7444
+ };
7445
+ maxPosts: {
7446
+ type: string;
7447
+ description: string;
7448
+ };
7449
+ maxEngagerPages: {
7450
+ type: string;
7451
+ description: string;
7452
+ };
7453
+ dryRunFingerprint: {
7454
+ type: string;
7455
+ description: string;
7456
+ };
7457
+ };
7458
+ required: string[];
7459
+ additionalProperties: boolean;
7460
+ };
7389
7461
  } | {
7390
7462
  name: string;
7391
7463
  description: string;
@@ -7446,22 +7518,6 @@ export declare const allTools: ({
7446
7518
  type: string;
7447
7519
  enum: string[];
7448
7520
  };
7449
- targetDate: {
7450
- type: string;
7451
- pattern: string;
7452
- description: string;
7453
- };
7454
- untilDate: {
7455
- type: string;
7456
- pattern: string;
7457
- description: string;
7458
- };
7459
- horizonSendDays: {
7460
- type: string;
7461
- minimum: number;
7462
- maximum: number;
7463
- description: string;
7464
- };
7465
7521
  };
7466
7522
  required: string[];
7467
7523
  additionalProperties: boolean;
@@ -34,6 +34,7 @@ import { onDemandToolDefinitions } from "./one-off.js";
34
34
  import { processingToolDefinitions } from "./processing.js";
35
35
  import { promptToolDefinitions } from "./prompts.js";
36
36
  import { readinessToolDefinitions } from "./readiness.js";
37
+ import { refreshSenderEngagementToolDefinitions } from "./refresh-sender-engagement.js";
37
38
  import { refillSendsV2ToolDefinitions } from "./refill-sends-v2.js";
38
39
  import { refillSendsToolDefinitions } from "./refill-sends.js";
39
40
  import { refillTargetPlanToolDefinitions } from "./refill-target-plan.js";
@@ -83,6 +84,7 @@ export const allTools = [
83
84
  ...processingToolDefinitions,
84
85
  ...rubricToolDefinitions,
85
86
  ...readinessToolDefinitions,
87
+ ...refreshSenderEngagementToolDefinitions,
86
88
  ...rowToolDefinitions,
87
89
  ...cellToolDefinitions,
88
90
  ...promptToolDefinitions,
@@ -10,7 +10,7 @@ async function postSchedulerFillCapacity(body, workspaceId) {
10
10
  export const schedulerFillCapacityToolDefinitions = [
11
11
  {
12
12
  name: "get_scheduler_fill_capacity",
13
- description: "read-only scheduler capacity query for refill-sends before any refill mutation. It asks the product scheduler model how many additional cells the scheduler will try to place for exact sender/action requests, using the default scheduler-forward horizon or one exact targetDate. Use get_refill_target_plan for multi-day untilDate or horizonSendDays planning. It returns scheduler-fillable slots, occupied scheduled/processing slots, sender sendability gates, cooldowns, Sales Navigator status for paid InMail, cached paid-InMail credit feasibility, threshold source, blockers, warnings, and explicit sideEffects false. This tool does not create rows, import leads, prepare messages, approve messages, does not schedule sends, does not refresh paid InMail credits, mutate thresholds, start campaigns, launch, or send. Use exact senderId values only; never pass sender names.",
13
+ description: "read-only scheduler capacity query for refill-sends before any refill mutation. It asks the product scheduler model how many additional cells the scheduler will try to place for exact sender/action requests, using the default scheduler-forward horizon or one exact targetDate. It returns scheduler-fillable slots, occupied scheduled/processing slots, sender sendability gates, cooldowns, Sales Navigator status for paid InMail, cached paid-InMail credit feasibility, threshold source, blockers, warnings, and explicit sideEffects false. This tool does not create rows, import leads, prepare messages, approve messages, does not schedule sends, does not refresh paid InMail credits, mutate thresholds, start campaigns, launch, or send. Use exact senderId values only; never pass sender names.",
14
14
  inputSchema: {
15
15
  type: "object",
16
16
  properties: {
@@ -2,7 +2,7 @@ type SchedulerRunAction = "run" | "status";
2
2
  type RunSchedulerSweepInput = {
3
3
  workspaceId: string;
4
4
  action?: SchedulerRunAction;
5
- targetDate?: string | null;
5
+ targetDate?: string;
6
6
  };
7
7
  export declare const schedulerRunToolDefinitions: {
8
8
  name: string;
@@ -7,10 +7,24 @@ async function postSchedulerRun(body, workspaceId) {
7
7
  ? api.post("/api/v3/mcp/scheduler-run", body, requestOptions)
8
8
  : api.post("/api/v3/mcp/scheduler-run", body);
9
9
  }
10
+ function normalizeTargetDate(value) {
11
+ if (typeof value !== "string" || !value.trim())
12
+ return null;
13
+ const targetDate = value.trim();
14
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(targetDate)) {
15
+ throw new Error("targetDate must use YYYY-MM-DD format.");
16
+ }
17
+ const parsed = new Date(`${targetDate}T00:00:00.000Z`);
18
+ if (Number.isNaN(parsed.getTime()) ||
19
+ parsed.toISOString().slice(0, 10) !== targetDate) {
20
+ throw new Error("targetDate must be a valid calendar date.");
21
+ }
22
+ return targetDate;
23
+ }
10
24
  export const schedulerRunToolDefinitions = [
11
25
  {
12
26
  name: "run_scheduler_sweep",
13
- description: 'Trigger the product scheduler placement sweep for one explicit workspace now, or read the last on-demand scheduler run status with action "status". By default a run is workspace-wide, not a scoped run for one campaign/table. Pass targetDate to scope placement to one exact sender-local date while still remaining workspace-wide inside that date. Multi-day untilDate or horizonSendDays planning should come from get_refill_target_plan, then use exact per-date run_scheduler_sweep calls only for dates that still need scheduler placement. The synchronous envelope includes status ran, attached, backoff, window_closed_noop, or failed; retryAfterMs for matching-scope backoff replays; and a backward-compatible receipt with public scope metadata. In v2 receipts, readyCellsFound is total scheduler-ready supply found before filters, cellsConsidered is the allocation-attempt count that survived prefilters, prefiltered means ready cells removed before allocation such as no capacity, stale paid InMail credit facts, or sender mismatch, skipped means considered cells rejected by hard scheduler gates, and deferred means considered cells waiting on windows/capacity/cooldown. campaignScopeSummary lists bounded tables/campaigns the workspace-wide run inspected; absence there is not a scoped-run guarantee that the target was ready. The receipt can include readyCellsByType, consideredCellsByType, prefilterReasons, skippedReasons, deferredReasons, summary, and nextAction. It places cells within existing scheduler gates only: it can move placement earlier, but it cannot bypass sending windows, daily limits, cooldowns, sender gates, billing, or credit thresholds, and it never sends messages directly. Repeated calls inside the backoff window replay the last receipt only when the recorded public scope matches this request. Status is read-only and scoped to the last on-demand run only; cron sweeps are not recorded here.',
27
+ description: 'Trigger the product scheduler placement sweep for one explicit workspace now, or read the last on-demand scheduler run status with action "status". A run is workspace-wide, not a scoped run for one campaign/table, and returns a synchronous envelope with status ran, attached, backoff, window_closed_noop, or failed; retryAfterMs for backoff replays; and a backward-compatible receipt. In v2 receipts, readyCellsFound is total scheduler-ready supply found before filters, cellsConsidered is the allocation-attempt count that survived prefilters, prefiltered means ready cells removed before allocation such as no capacity, stale paid InMail credit facts, or sender mismatch, skipped means considered cells rejected by hard scheduler gates, and deferred means considered cells waiting on windows/capacity/cooldown. campaignScopeSummary lists bounded tables/campaigns the workspace-wide run inspected; absence there is not a scoped-run guarantee that the target was ready. The receipt can include readyCellsByType, consideredCellsByType, prefilterReasons, skippedReasons, deferredReasons, summary, and nextAction. It places cells within existing scheduler gates only: it can move placement earlier, but it cannot bypass sending windows, daily limits, cooldowns, sender gates, billing, or credit thresholds, and it never sends messages directly. Repeated calls inside the backoff window replay the last receipt verbatim. Status is read-only and scoped to the last on-demand run only; cron sweeps are not recorded here.',
14
28
  inputSchema: {
15
29
  type: "object",
16
30
  properties: {
@@ -33,36 +47,19 @@ export const schedulerRunToolDefinitions = [
33
47
  },
34
48
  },
35
49
  ];
36
- function isValidDateKey(value) {
37
- if (!/^\d{4}-\d{2}-\d{2}$/.test(value))
38
- return false;
39
- const [year, month, day] = value.split("-").map(Number);
40
- const date = new Date(Date.UTC(year, month - 1, day));
41
- return (date.getUTCFullYear() === year &&
42
- date.getUTCMonth() === month - 1 &&
43
- date.getUTCDate() === day);
44
- }
45
- function normalizeTargetDate(value) {
46
- if (value === undefined)
47
- return undefined;
48
- if (typeof value !== "string" || !isValidDateKey(value)) {
49
- throw new Error("targetDate must be a valid YYYY-MM-DD calendar date.");
50
- }
51
- return value;
52
- }
53
50
  export async function runSchedulerSweep(input) {
54
51
  const workspaceId = normalizeExplicitWorkspaceId(input.workspaceId);
55
52
  if (!workspaceId) {
56
53
  throw new Error("workspaceId is required for run_scheduler_sweep.");
57
54
  }
58
55
  const action = input.action ?? "run";
56
+ const targetDate = normalizeTargetDate(input.targetDate);
59
57
  if (action !== "run" && action !== "status") {
60
58
  throw new Error('action must be "run" or "status" for run_scheduler_sweep.');
61
59
  }
62
- const targetDate = normalizeTargetDate(input.targetDate);
63
60
  return postSchedulerRun({
64
61
  workspaceId,
65
62
  action,
66
- targetDate,
63
+ ...(targetDate ? { targetDate } : {}),
67
64
  }, workspaceId);
68
65
  }
@@ -52,16 +52,22 @@ export type PaidInmailCreditStatus = {
52
52
  };
53
53
  export type RefreshPaidInmailCreditsResponse = {
54
54
  senderId: string;
55
- refreshed: true;
55
+ refreshed: boolean;
56
+ error?: string | null;
56
57
  credits: PaidInmailCreditStatus;
57
- receipt?: unknown;
58
+ receipt?: {
59
+ status?: string;
60
+ refreshed?: boolean;
61
+ error?: string;
62
+ [key: string]: unknown;
63
+ } | null;
58
64
  sideEffects: {
59
- refreshedLinkedInDerivedCreditFacts: true;
60
- updatedSenderCreditCache: true;
61
- campaignMutation: false;
62
- schedulerMutation: false;
63
- thresholdMutation: false;
64
- sendMutation: false;
65
+ refreshedLinkedInDerivedCreditFacts: boolean;
66
+ updatedSenderCreditCache: boolean;
67
+ campaignMutation: boolean;
68
+ schedulerMutation: boolean;
69
+ thresholdMutation: boolean;
70
+ sendMutation: boolean;
65
71
  };
66
72
  };
67
73
  export declare const senderToolDefinitions: ({
@@ -237,6 +237,21 @@ function normalizeCreditStatus(raw) {
237
237
  needsRefresh: raw?.needsRefresh === true,
238
238
  };
239
239
  }
240
+ function normalizeRefreshReceipt(raw) {
241
+ if (!raw || typeof raw !== "object")
242
+ return null;
243
+ return raw;
244
+ }
245
+ function normalizeCreditRefreshSideEffects(raw, receiptRefreshed) {
246
+ return {
247
+ refreshedLinkedInDerivedCreditFacts: raw?.refreshedLinkedInDerivedCreditFacts === true || receiptRefreshed,
248
+ updatedSenderCreditCache: raw?.updatedSenderCreditCache === true || receiptRefreshed,
249
+ campaignMutation: raw?.campaignMutation === true,
250
+ schedulerMutation: raw?.schedulerMutation === true,
251
+ thresholdMutation: raw?.thresholdMutation === true,
252
+ sendMutation: raw?.sendMutation === true,
253
+ };
254
+ }
240
255
  export async function refreshPaidInmailCredits(input) {
241
256
  const senderId = input.senderId?.trim();
242
257
  if (!senderId) {
@@ -268,18 +283,14 @@ export async function refreshPaidInmailCredits(input) {
268
283
  if (threshold !== null)
269
284
  body.threshold = threshold;
270
285
  const result = await api.post(`/api/v3/mcp/senders/${encodeURIComponent(senderId)}/refresh-inmail-credits`, body, requestOptions);
286
+ const receipt = normalizeRefreshReceipt(result?.receipt);
287
+ const receiptRefreshed = result?.refreshed === true || receipt?.refreshed === true;
271
288
  return {
272
289
  senderId,
273
- refreshed: true,
290
+ refreshed: receiptRefreshed,
291
+ error: pickString(result?.error, receipt?.error),
274
292
  credits: normalizeCreditStatus(result?.credits),
275
- receipt: result?.receipt,
276
- sideEffects: {
277
- refreshedLinkedInDerivedCreditFacts: true,
278
- updatedSenderCreditCache: true,
279
- campaignMutation: false,
280
- schedulerMutation: false,
281
- thresholdMutation: false,
282
- sendMutation: false,
283
- },
293
+ receipt,
294
+ sideEffects: normalizeCreditRefreshSideEffects(result?.sideEffects, receiptRefreshed),
284
295
  };
285
296
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.540",
3
+ "version": "0.1.542",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code, Codex, and Hermes campaign workflows",
6
6
  "main": "dist/index.js",
@@ -87,12 +87,6 @@ Accepted invocation flags in the same user request:
87
87
  preserves natural-language arguments better than shell-style flags.
88
88
  - `targetDate: YYYY-MM-DD`: exact-date selector alternative when the host
89
89
  preserves natural-language arguments better than shell-style flags.
90
- - `horizonSendDays: N`: compatibility selector for the next N sender-local send
91
- days when no exact or through-date selector is present.
92
-
93
- Date selector precedence is `targetDate > untilDate > horizonSendDays`. Use
94
- `targetDate` for one exact sender-local date, `untilDate` for an inclusive
95
- through-date, and `horizonSendDays` for the next N sender-local send days.
96
90
 
97
91
  When the host can call typed MCP tools, start with:
98
92
 
@@ -278,9 +272,7 @@ same sender/action/date; it tells the MCP how many cells the product scheduler
278
272
  will try to place and does not import, approve, schedule, refresh credits, or
279
273
  mutate.
280
274
  When the refill loop has ready rows and needs scheduler pickup now, use
281
- `run_scheduler_sweep({ workspaceId, targetDate })` for exact-date requests. For
282
- `untilDate` or `horizonSendDays` requests, sweep each planner-selected
283
- `targetDate` with the same explicit `workspaceId`. The sweep can place cells
275
+ `run_scheduler_sweep` with the same explicit `workspaceId`; it can place cells
284
276
  within existing scheduler gates and returns the receipt, but it never sends or
285
277
  bypasses limits.
286
278
  Scheduler-run receipt interpretation: `cellsConsidered is allocation-attempt
@@ -37,21 +37,16 @@ active workspace readback. Scheduled or autonomous usage must carry
37
37
  `workspaceId` on every tool call. If the workspace is missing or ambiguous, stop
38
38
  with `WORKSPACE_REQUIRED`; do not switch the shared active workspace.
39
39
 
40
- Date selectors are sender-local and mutually exclusive by precedence:
41
- `targetDate > untilDate > horizonSendDays`. Use `targetDate` for one exact sender-local date, `untilDate` for an inclusive through-date, and `horizonSendDays` for the next N sender-local send days. If none is provided, the planner uses the default scheduler-forward 48-hour behavior.
42
-
43
40
  For a real refill run:
44
41
 
45
42
  ```text
46
- refill_sends_v2({ workspaceId, intent:"auto", senderIds?, approvalMode?, targetDate?, untilDate?, horizonSendDays? })
47
- refill_sends_v2({ workspaceId, targetDate:"2026-07-07" })
48
- refill_sends_v2({ workspaceId, untilDate:"2026-07-09" })
43
+ refill_sends_v2({ workspaceId, intent:"auto", senderIds?, approvalMode? })
49
44
  ```
50
45
 
51
46
  For read-only inspection:
52
47
 
53
48
  ```text
54
- refill_sends_v2({ workspaceId, dryRun:true, intent:"auto", senderIds?, targetDate?, untilDate?, horizonSendDays? })
49
+ refill_sends_v2({ workspaceId, dryRun:true, intent:"auto", senderIds? })
55
50
  ```
56
51
 
57
52
  To resume an in-progress run, pass the handle back exactly:
@@ -60,11 +55,6 @@ To resume an in-progress run, pass the handle back exactly:
60
55
  refill_sends_v2({ workspaceId, runId, fence })
61
56
  ```
62
57
 
63
- The original run's date window is stored in the run record. On resume, the
64
- stored window is reused and conflicting resume input is blocked; do not add,
65
- change, or remove `targetDate`, `untilDate`, or `horizonSendDays` while passing
66
- an existing `{ runId, fence }`.
67
-
68
58
  If a stale handle loses the lease, the tool reports the holder status and the
69
59
  approximately 10 minute lockout window. Reinvoke with the current handle or wait
70
60
  for lease expiry; never guess a fence.
@@ -135,12 +125,9 @@ host guard, heartbeats the run lease, and may return:
135
125
  ```
136
126
 
137
127
  Reinvoke with that handle. The approximately five minute scheduler budget is at
138
- the run level, not one tool call. Exact-date runs request pickup with
139
- `run_scheduler_sweep({ workspaceId, targetDate })`; `untilDate` and
140
- `horizonSendDays` runs sweep each planner-selected exact target date. A
141
- window-closed or loaded-awaiting scheduler report must include remaining-ready
142
- count, exact expected pickup time, and the resume handle; never treat bare
143
- "awaiting scheduler" copy as a final answer.
128
+ the run level, not one tool call. A window-closed or loaded-awaiting scheduler
129
+ report must include remaining-ready count, exact expected pickup time, and the
130
+ resume handle; never treat bare "awaiting scheduler" copy as a final answer.
144
131
  Scheduler-run receipt interpretation still applies to terminal progress:
145
132
  `cellsConsidered is allocation-attempt count`, not total ready supply, while
146
133
  `readyCellsFound` is ready inventory found before prefilters. Inspect
@@ -33,16 +33,10 @@ local files or memory.
33
33
  Resolve request-scoped `workspaceId` using read-only auth and workspace tools.
34
34
  Scheduled or autonomous runs must not rely on implicit workspace state.
35
35
 
36
- Carry the request date selector through bootstrap, planning, execution, and
37
- resume. Date selector precedence is `targetDate > untilDate > horizonSendDays`:
38
- `targetDate` is one exact sender-local date, `untilDate` is an inclusive
39
- through-date, and `horizonSendDays` is the next N sender-local send days. If no
40
- selector is present, use the default scheduler-forward 48-hour behavior.
41
-
42
36
  Start or resume the execution loop:
43
37
 
44
38
  ```text
45
- refill_sends_v2({ workspaceId, intent:"auto", senderIds?, approvalMode?, targetDate?, untilDate?, horizonSendDays?, runId?, fence? })
39
+ refill_sends_v2({ workspaceId, intent:"auto", senderIds?, approvalMode?, runId?, fence? })
46
40
  ```
47
41
 
48
42
  Use `dryRun:true` only when the user asked for read-only inspection. A dry run
@@ -50,11 +44,6 @@ writes a journal only. A real run creates or resumes a run record, refreshes
50
44
  paid-credit trust only when packet facts require it, and returns a resume handle
51
45
  when the current invocation must pause.
52
46
 
53
- The run record stores the selected date window. On resume, reuse that stored
54
- window and block conflicting resume input; do not accept a changed
55
- `targetDate`, `untilDate`, or `horizonSendDays` with an existing `{ runId,
56
- fence }`.
57
-
58
47
  ## G1 Plan
59
48
 
60
49
  The loop reads `get_refill_plan_v2` with runState fed back from the run record.
@@ -127,10 +116,7 @@ outcome, then verifies before replanning.
127
116
  Scheduler wait is cross-invocation. If the tool returns `in_progress` with
128
117
  sweep guidance, re-invoke `refill_sends_v2` with `{runId, fence}`. The scheduler
129
118
  budget is cumulative at the run level. Zero pickup after a confirmed sweep is
130
- debugged from `pipelineDiagnosis`; it is not waited out forever. Exact-date
131
- runs request pickup with `run_scheduler_sweep({ workspaceId, targetDate })`;
132
- `untilDate` and `horizonSendDays` runs sweep each planner-selected exact target
133
- date.
119
+ debugged from `pipelineDiagnosis`; it is not waited out forever.
134
120
  Scheduler-run receipt interpretation still applies to terminal progress:
135
121
  `cellsConsidered is allocation-attempt count`, not total ready supply, while
136
122
  `readyCellsFound` is ready inventory found before prefilters. Inspect
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "v1.0",
3
3
  "workflow": "refill-sends-v2-workflow",
4
- "principle": "Execute refill sends v2 through a fenced run record: bootstrap, plan, execute, verify, and report. Dry runs stay read-only; real runs execute only packet-named bounded work. Date selectors use targetDate > untilDate > horizonSendDays precedence.",
4
+ "principle": "Execute refill sends v2 through a fenced run record: bootstrap, plan, execute, verify, and report. Dry runs stay read-only; real runs execute only packet-named bounded work.",
5
5
  "laneSources": [
6
6
  "managed_waterfall",
7
7
  "dashboard_evergreen",
@@ -50,9 +50,6 @@
50
50
  "repair rungs come from the plan packet; the loop bounds and refuses, never self-emits repair actions",
51
51
  "capped_by_scheduler is complete, never poll",
52
52
  "awaiting scheduler is not an end state; window-closed reports name remaining-ready, expected pickup time, and resume handle",
53
- "date selectors resolve by targetDate > untilDate > horizonSendDays; targetDate is one exact sender-local date, untilDate is an inclusive through-date, and horizonSendDays means next N sender-local send days",
54
- "dateWindow is stored on the run record and conflicting resume input is blocked",
55
- "exact-date scheduler pickup uses run_scheduler_sweep({ workspaceId, targetDate }); untilDate and horizonSendDays runs sweep each planner-selected exact targetDate",
56
53
  "honest-rubric-fail means a human updates the rubric or changes lead source",
57
54
  "source replenishment beyond same-source-automatic is a scoped create-campaign handoff, never refill-owned provider search",
58
55
  "no campaign creation, provider-family switch, threshold lowering, scheduler writes, sends, archives, deletes, or brief/filter/message/sequence/sender mutation without a separate approval packet"
@@ -146,16 +143,7 @@
146
143
  },
147
144
  {
148
145
  "tool": "refill_sends_v2",
149
- "requiredFields": ["workspaceId"],
150
- "optionalFields": [
151
- "senderIds",
152
- "approvalMode",
153
- "targetDate",
154
- "untilDate",
155
- "horizonSendDays",
156
- "runId",
157
- "fence"
158
- ]
146
+ "requiredFields": ["workspaceId"]
159
147
  },
160
148
  {
161
149
  "tool": "get_subskill_prompt",
@@ -188,9 +176,6 @@
188
176
  "optionalFields": [
189
177
  "intent",
190
178
  "senderIds",
191
- "targetDate",
192
- "untilDate",
193
- "horizonSendDays",
194
179
  "runState",
195
180
  "journal",
196
181
  "journalNote"
@@ -326,7 +311,7 @@
326
311
  },
327
312
  {
328
313
  "id": "verify",
329
- "description": "Verify whole-row outcomes before another plan read. Reattach to an own active prep job by requestSource/requestHash; never re-dispatch prep while a matching job is active. Foreign prep waits until clear or blocks foreign_prep_active. wait_for_active_work and wait_for_source_import reread the plan on bounded cadence. wait_for_scheduler is cross-invocation: each tool call polls briefly under the host guard, heartbeats the lease, and returns in_progress sweep guidance so the agent re-invokes refill_sends_v2 with {runId,fence}. Exact-date scheduler pickup uses run_scheduler_sweep({ workspaceId, targetDate }); untilDate and horizonSendDays runs sweep each planner-selected exact targetDate. The approximately five minute scheduler budget is cumulative at the run level.",
314
+ "description": "Verify whole-row outcomes before another plan read. Reattach to an own active prep job by requestSource/requestHash; never re-dispatch prep while a matching job is active. Foreign prep waits until clear or blocks foreign_prep_active. wait_for_active_work and wait_for_source_import reread the plan on bounded cadence. wait_for_scheduler is cross-invocation: each tool call polls briefly under the host guard, heartbeats the lease, and returns in_progress sweep guidance so the agent re-invokes refill_sends_v2 with {runId,fence}. The approximately five minute scheduler budget is cumulative at the run level.",
330
315
  "allowedTools": ["refill_sends_v2", "get_refill_plan_v2"],
331
316
  "onEnter": [
332
317
  {
@@ -337,7 +322,6 @@
337
322
  "hardRules": [
338
323
  "do not re-dispatch prep when an own active job exists; reattach and poll status",
339
324
  "capped_by_scheduler is complete",
340
- "resume uses the stored dateWindow; conflicting resume input is blocked",
341
325
  "replan-driven repair: the planner names rerun_errored_cells, approve_messages, start_campaign, or source work; the loop bounds and refuses",
342
326
  "conversion verdict is journaled from packet facts after the first prep batch; the plan gate withholds a second unproven prep batch",
343
327
  "zero pickup after a confirmed sweep is debugged from pipelineDiagnosis, not waited out forever",
@@ -189,11 +189,9 @@ files or memory.
189
189
  does not create rows, import, approve, schedule, refresh paid-InMail credits,
190
190
  or mutate thresholds.
191
191
  When ready rows exist and the wait is for scheduler pickup, call
192
- `run_scheduler_sweep({ workspaceId, targetDate })` for exact-date requests
193
- to request the product scheduler placement pass now and read its receipt. For
194
- `untilDate` or `horizonSendDays` requests, sweep each planner-selected
195
- `targetDate` with the same explicit `workspaceId`. This may place cells
196
- within existing gates, never sends messages, and never bypasses limits.
192
+ `run_scheduler_sweep` with the same explicit `workspaceId` to request the
193
+ product scheduler placement pass now and read its receipt. This may place
194
+ cells within existing gates, never sends messages, and never bypasses limits.
197
195
  Scheduler-run receipt interpretation: `cellsConsidered is
198
196
  allocation-attempt count`, not total ready supply, while `readyCellsFound`
199
197
  is ready inventory found before prefilters. Inspect `campaignScopeSummary`
@@ -202,7 +202,7 @@
202
202
  ],
203
203
  "rules": [
204
204
  "Poll every 60-120 seconds or on the host continuation interval.",
205
- "Use run_scheduler_sweep({ workspaceId, targetDate }) for exact-date scheduler pickup; for untilDate or horizonSendDays requests, sweep each planner-selected targetDate with the explicit workspaceId. It places cells only inside existing gates and never sends.",
205
+ "Use run_scheduler_sweep with the explicit workspaceId when ready rows need scheduler pickup now; it places cells only inside existing gates and never sends.",
206
206
  "cellsConsidered is allocation-attempt count; inspect campaignScopeSummary before assuming the selected refill campaign/table was included or ready-but-blocked.",
207
207
  "Read prefiltered, skipped, and deferred separately: prefiltered ready closed-InMail cells with stale paid-credit facts require refresh_paid_inmail_credits_then_rerun once, then rerun/status.",
208
208
  "wait_for_capacity_or_window means report loaded/capped/waiting and do not source or prep more rows; no_ready_cells_continue_refill_prep means return to the refill/prep ladder.",