@sellable/mcp 0.1.558 → 0.1.559

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.
@@ -361,11 +361,17 @@ function actionSenderId(action) {
361
361
  }
362
362
  function fingerprintFromPlan(plan) {
363
363
  const packet = recordValue(plan.packet) ?? {};
364
+ const targetShapeRevision = stringValue(packet.targetShapeRevision) ??
365
+ stringValue(packet.targetRevision) ??
366
+ stringValue(plan.targetShapeRevision) ??
367
+ stringValue(plan.targetRevision);
364
368
  return {
365
- planRevision: stringValue(plan.planRevision),
369
+ // Evergreen packets carry their own semantic plan revision. Regular
370
+ // active-campaign packets intentionally do not, so their immutable target
371
+ // shape is the durable planning revision for fencing and recovery.
372
+ planRevision: stringValue(plan.planRevision) ?? targetShapeRevision,
366
373
  stateRevision: stringValue(plan.stateRevision) ?? stringValue(packet.stateRevision),
367
- targetShapeRevision: stringValue(packet.targetShapeRevision) ??
368
- stringValue(packet.targetRevision),
374
+ targetShapeRevision,
369
375
  };
370
376
  }
371
377
  function fingerprintChanged(expected, actual) {
@@ -189,7 +189,7 @@ export const refillSendsToolDefinitions = [
189
189
  },
190
190
  expectedActionKey: {
191
191
  type: "string",
192
- description: "Optional actionKey from the approved packet's first global action. A mismatch returns approval_scope_changed before any refresh or mutation.",
192
+ description: "Optional actual non-empty actionKey from the approved packet's first global action. Never infer it from type, toolName, or actionFingerprint. A mismatch returns approval_scope_changed before any refresh or mutation.",
193
193
  },
194
194
  runId: { type: "string" },
195
195
  fence: { type: "number" },
@@ -293,7 +293,7 @@ function buildRefillSendsCommand(input) {
293
293
  : `, horizonSendDays: ${horizonSendDays}`}, approvalMode: "${approvalMode}" }) before any import, prep, approval, start, or schedule-affecting action.`,
294
294
  "Render target.eligibleSenderLedger and target.senderRefillPlans before mutation. Preserve the coverage labels Need to prepare, Goal, Already sent, Scheduled, Ready and waiting to be scheduled, and Still need.",
295
295
  "Use target.globalActionQueue as the only cross-sender yolo queue: execute only target.globalActionQueue[0], one globally ranked primitive, then rerun get_refill_target_plan before choosing another action.",
296
- "When expectedTargetShapeRevision or expectedActionKey is supplied from an already rendered packet, compare both against the first fresh target plan before paid-credit refresh or any primitive. Return approval_scope_changed with the fresh packet on mismatch.",
296
+ "When expectedTargetShapeRevision or expectedActionKey is supplied from an already rendered packet, compare both against the first fresh target plan before paid-credit refresh or any primitive. Pass expectedActionKey only when the rendered action has an actual non-empty actionKey; never infer it from type, toolName, or actionFingerprint. Return approval_scope_changed with the fresh packet on mismatch.",
297
297
  "Read target.senderRefillPlans[].refillReceipt as the public ladder receipt: it carries the selected campaign/sender/lane summary, skippedRungs, existingRowFrontier, and any absolute wait.deadlineAt. Do not choose source/copy/fallback work until that receipt proves the earlier ready/prep/approval rungs are exhausted.",
298
298
  "If get_refill_target_plan returns status complete, report eligible sender ledger, target.senderRefillPlans, gross target, selected days, sent count, scheduled count, projected count, campaign ids, targetShapeRevision, and no-op proof without asking for approval.",
299
299
  "Refill target lanes are connection invites (send_invite), standalone paid InMails (send_inmail_closed), or unified Sales Nav cascades represented publicly as send_inmail_closed with campaign classification sales_nav_cascade. For a Sales Nav cascade, refill the selected campaign first; its sequence can route prospects to Open InMail, paid InMail while fresh credits are >= 5, or same-campaign connection fallback without asking for separate open/paid/connection campaigns. Do not count send_dm as horizon target capacity.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.558",
3
+ "version": "0.1.559",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code, Codex, and Hermes campaign workflows",
6
6
  "main": "dist/index.js",
@@ -101,6 +101,9 @@ Claude Code uses `/sellable:refill-sends`. Optional selectors are `--sender`,
101
101
  6. Invoke only the public durable entrypoint:
102
102
  `mcp__sellable__refill_sends({ workspaceId, targetDate, untilDate, horizonSendDays, senderIds, senderNames, actionTypes, yolo, executionMode, requireWorkspace:true })`.
103
103
  Preserve the exact scope and approval echo returned by the tool on resume.
104
+ Pass `expectedActionKey` only when the rendered first global action contains
105
+ an actual non-empty `actionKey`; never infer it from `type`, `toolName`, or
106
+ `actionFingerprint`.
104
107
 
105
108
  ## Operator packet
106
109