@sellable/mcp 0.1.736 → 0.1.737

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.
@@ -166,6 +166,11 @@ declare function dominantSchedulerRefusalReason(receipt: Record<string, unknown>
166
166
  reason: string;
167
167
  count: number;
168
168
  } | null;
169
+ type SchedulerRefusalDisposition = {
170
+ retryable: boolean | null;
171
+ blockerClass: "transient_or_refreshable" | "time_bound_capacity" | "operator_action_required" | "unknown";
172
+ };
173
+ declare function classifySchedulerRefusal(reason: string | null): SchedulerRefusalDisposition;
169
174
  declare function schedulerSweepNoOpBlocker(ctx: LoopContext, reportInput: Record<string, unknown>): Record<string, unknown> | null;
170
175
  export declare function packetCoherenceFailure(plan: Record<string, unknown>): string | null;
171
176
  export declare function terminalProjection(value: {
@@ -184,5 +189,6 @@ export declare function runRefillV2Loop(input: RefillV2LoopInput, deps: RefillV2
184
189
  export declare const refillRunLoopInternals: {
185
190
  schedulerSweepNoOpBlocker: typeof schedulerSweepNoOpBlocker;
186
191
  dominantSchedulerRefusalReason: typeof dominantSchedulerRefusalReason;
192
+ classifySchedulerRefusal: typeof classifySchedulerRefusal;
187
193
  };
188
194
  export {};
@@ -432,6 +432,24 @@ function dominantSchedulerRefusalReason(receipt) {
432
432
  }
433
433
  return null;
434
434
  }
435
+ function classifySchedulerRefusal(reason) {
436
+ if (!reason)
437
+ return { retryable: null, blockerClass: "unknown" };
438
+ // Infrastructure or freshness failures: the underlying facts can be re-read
439
+ // and the same sweep can then succeed without anyone changing configuration.
440
+ if (/(pool|timeout|timed[_ -]?out|connection|transient|unavailable|receipt[_ -]?invalid|stale|refresh)/i.test(reason)) {
441
+ return { retryable: true, blockerClass: "transient_or_refreshable" };
442
+ }
443
+ // Time-bound capacity: nothing is broken, the slot simply is not open yet.
444
+ if (/(window|capacity|daily[_ -]?limit|cooldown|rate[_ -]?limit)/i.test(reason)) {
445
+ return { retryable: true, blockerClass: "time_bound_capacity" };
446
+ }
447
+ // Standing gates: re-running cannot clear these; a human must act.
448
+ if (/(billing|credit[_ -]?threshold|disconnected|sender[_ -]?mismatch|not[_ -]?scheduler[_ -]?eligible|suspended|unauthor)/i.test(reason)) {
449
+ return { retryable: false, blockerClass: "operator_action_required" };
450
+ }
451
+ return { retryable: null, blockerClass: "unknown" };
452
+ }
435
453
  // fix(112al): a sweep whose own receipt proves it placed zero while ready
436
454
  // inventory existed. Gated on the executed action actually being a scheduler
437
455
  // sweep and on a FRESH terminal receipt (ran / window_closed_noop), so an
@@ -461,8 +479,9 @@ function schedulerSweepNoOpBlocker(ctx, reportInput) {
461
479
  dominantReason: dominant.reason,
462
480
  dominantReasonSource: dominant.source,
463
481
  dominantReasonCount: dominant.count,
482
+ ...classifySchedulerRefusal(dominant.reason),
464
483
  }
465
- : {}),
484
+ : classifySchedulerRefusal(null)),
466
485
  ...(stringValue(receipt?.nextAction)
467
486
  ? { recommendedAction: stringValue(receipt?.nextAction) }
468
487
  : {}),
@@ -4806,4 +4825,5 @@ export async function runRefillV2Loop(input, deps) {
4806
4825
  export const refillRunLoopInternals = {
4807
4826
  schedulerSweepNoOpBlocker,
4808
4827
  dominantSchedulerRefusalReason,
4828
+ classifySchedulerRefusal,
4809
4829
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.736",
3
+ "version": "0.1.737",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code, Codex, and Hermes campaign workflows",
6
6
  "main": "dist/index.js",