@sellable/mcp 0.1.729 → 0.1.731

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.
@@ -3232,6 +3232,123 @@ export declare function executeRefillSendsCommand(input?: RefillSendsCommandInpu
3232
3232
  workspaceId: string | null;
3233
3233
  workspaceResolution: string;
3234
3234
  intent: RefillSendsIntent;
3235
+ } | {
3236
+ ok: boolean;
3237
+ status: string;
3238
+ blocker: string;
3239
+ note: string;
3240
+ coordinator: {
3241
+ scope: "workspace";
3242
+ status: "blocked";
3243
+ backgroundJob?: undefined;
3244
+ workspaceTargetPlan?: undefined;
3245
+ selectedTarget?: undefined;
3246
+ waitAction?: undefined;
3247
+ exactTargetPlan?: undefined;
3248
+ note?: undefined;
3249
+ completedTarget?: undefined;
3250
+ exactRunResult?: undefined;
3251
+ handBack?: undefined;
3252
+ };
3253
+ continuation: {
3254
+ required: boolean;
3255
+ userActionRequired: boolean;
3256
+ renderBeforeInvoke?: undefined;
3257
+ kind?: undefined;
3258
+ tool?: undefined;
3259
+ arguments?: undefined;
3260
+ owner?: undefined;
3261
+ retryAfterMs?: undefined;
3262
+ stopCondition?: undefined;
3263
+ };
3264
+ targetDate: string | null;
3265
+ untilDate: string | null;
3266
+ horizonSendDays: number | null;
3267
+ fillWindow: {
3268
+ mode: string;
3269
+ targetDate: string;
3270
+ description: string;
3271
+ untilDate?: undefined;
3272
+ horizonSendDays?: undefined;
3273
+ horizonHours?: undefined;
3274
+ } | {
3275
+ mode: string;
3276
+ untilDate: string;
3277
+ description: string;
3278
+ targetDate?: undefined;
3279
+ horizonSendDays?: undefined;
3280
+ horizonHours?: undefined;
3281
+ } | {
3282
+ mode: string;
3283
+ horizonSendDays: number | null;
3284
+ horizonHours: number | null;
3285
+ description: string;
3286
+ targetDate?: undefined;
3287
+ untilDate?: undefined;
3288
+ };
3289
+ approvalMode: RefillSendsApprovalMode;
3290
+ campaignId: string | null;
3291
+ tableId: string | null;
3292
+ targetConfig: RefillTargetConfigV1 | null;
3293
+ runHandle: RefillRunHandleV1 | null;
3294
+ reportingContext: RefillReportingContextV2 | null;
3295
+ messageTemplateRevision: MessageTemplateRevisionV1 | null;
3296
+ senderScope: string;
3297
+ senderSelectors: {
3298
+ senders: string[];
3299
+ senderIds: string[];
3300
+ senderNames: string[];
3301
+ };
3302
+ firstOperationalSteps: string[];
3303
+ approvalContract: string;
3304
+ forbiddenActions: string[];
3305
+ hostExamples: {
3306
+ claude: string[];
3307
+ codex: string[];
3308
+ mcpTool: {
3309
+ name: string;
3310
+ arguments: {
3311
+ workspaceRunState?: Record<string, unknown> | undefined;
3312
+ workspaceCoordinator?: boolean | undefined;
3313
+ messageTemplateRevision?: MessageTemplateRevisionV1 | undefined;
3314
+ reportingContext?: RefillReportingContextV2 | undefined;
3315
+ targetConfig?: RefillTargetConfigV1 | undefined;
3316
+ runHandle?: RefillRunHandleV1 | undefined;
3317
+ fence?: number | undefined;
3318
+ runId?: string | undefined;
3319
+ expectedActionKey?: string | undefined;
3320
+ expectedTargetShapeRevision?: string | undefined;
3321
+ targetDate: string | null;
3322
+ untilDate: string | null;
3323
+ horizonSendDays: number | null;
3324
+ campaignId: string | undefined;
3325
+ tableId: string | undefined;
3326
+ intent: RefillSendsIntent;
3327
+ approvalMode: RefillSendsApprovalMode;
3328
+ workspaceId: string | null;
3329
+ actionTypes?: ("send_invite" | "send_inmail_closed")[] | undefined;
3330
+ yolo: boolean;
3331
+ senders: string[];
3332
+ senderIds: string[];
3333
+ senderNames: string[];
3334
+ };
3335
+ };
3336
+ };
3337
+ actionTypes?: ("send_invite" | "send_inmail_closed")[] | undefined;
3338
+ command: string;
3339
+ tool: string;
3340
+ promptName: string;
3341
+ workflowPromptName: string;
3342
+ workflowAsset: {
3343
+ subskillName: string;
3344
+ assetPath: string;
3345
+ expectedVersion: string;
3346
+ };
3347
+ yolo: boolean;
3348
+ executionMode: RefillSendsExecutionMode;
3349
+ workspaceId: string | null;
3350
+ workspaceResolution: string;
3351
+ intent: RefillSendsIntent;
3235
3352
  } | {
3236
3353
  targetPlan: unknown;
3237
3354
  orchestration: {
@@ -8397,6 +8514,273 @@ export declare function executeRefillSendsCommand(input?: RefillSendsCommandInpu
8397
8514
  workspaceId: string | null;
8398
8515
  workspaceResolution: string;
8399
8516
  intent: RefillSendsIntent;
8517
+ } | {
8518
+ status: "in_progress";
8519
+ note: string;
8520
+ targetPlan: unknown;
8521
+ exactTargetPlan: {} | null;
8522
+ orchestration: {
8523
+ mode: string;
8524
+ scope: string;
8525
+ phase: string;
8526
+ checkpointedFields?: undefined;
8527
+ transportBudgetMs?: undefined;
8528
+ };
8529
+ coordinator: {
8530
+ scope: string;
8531
+ status: string;
8532
+ completedTarget: WorkspaceExactTarget;
8533
+ selectedTarget: WorkspaceExactTarget;
8534
+ workspaceTargetPlan: unknown;
8535
+ exactRunResult: {
8536
+ status: "blocked";
8537
+ blocker: string;
8538
+ guidance: string;
8539
+ conflicts: string[];
8540
+ runId: string | undefined;
8541
+ readOnly: boolean;
8542
+ forbiddenActions: string[];
8543
+ boundedAuthority: string;
8544
+ } | {
8545
+ readOnly: boolean;
8546
+ mode: string;
8547
+ forbiddenActions: string[];
8548
+ boundedAuthority: string;
8549
+ blocker: string;
8550
+ workspaceId: string;
8551
+ guidance: string;
8552
+ warnings: string[];
8553
+ journalPath: string | null;
8554
+ text: string;
8555
+ workspaceResolution: string;
8556
+ status?: undefined;
8557
+ conflicts?: undefined;
8558
+ runId?: undefined;
8559
+ } | {
8560
+ readOnly: boolean;
8561
+ mode: string;
8562
+ forbiddenActions: string[];
8563
+ boundedAuthority: string;
8564
+ warnings: any[];
8565
+ journalPath: string | null;
8566
+ text: string;
8567
+ workspaceId: string;
8568
+ workspaceResolution: string;
8569
+ blocker?: undefined;
8570
+ guidance?: undefined;
8571
+ status?: undefined;
8572
+ conflicts?: undefined;
8573
+ runId?: undefined;
8574
+ } | {
8575
+ runSnapshot: unknown;
8576
+ readOnly: boolean;
8577
+ forbiddenActions: string[];
8578
+ boundedAuthority: string;
8579
+ status: "dry_run";
8580
+ plan: Record<string, unknown>;
8581
+ blocker?: undefined;
8582
+ guidance?: undefined;
8583
+ conflicts?: undefined;
8584
+ runId?: undefined;
8585
+ } | {
8586
+ runSnapshot: unknown;
8587
+ readOnly: boolean;
8588
+ forbiddenActions: string[];
8589
+ boundedAuthority: string;
8590
+ status: "in_progress";
8591
+ runId: string;
8592
+ fence: number;
8593
+ gate: import("../refill-run-loop.js").RefillLoopGate;
8594
+ guidance: string;
8595
+ journalPath?: string | null;
8596
+ targetConfig?: RefillTargetConfigV1;
8597
+ runHandle?: RefillRunHandleV1;
8598
+ refillReporting?: Record<string, unknown>;
8599
+ blocker?: undefined;
8600
+ conflicts?: undefined;
8601
+ } | {
8602
+ runSnapshot: unknown;
8603
+ readOnly: boolean;
8604
+ forbiddenActions: string[];
8605
+ boundedAuthority: string;
8606
+ status: "blocked";
8607
+ blocker: string;
8608
+ runId?: string;
8609
+ fence?: number;
8610
+ gate?: import("../refill-run-loop.js").RefillLoopGate;
8611
+ guidance: string;
8612
+ holderRunId?: string;
8613
+ report?: Record<string, unknown>;
8614
+ journalPath?: string | null;
8615
+ targetConfig?: RefillTargetConfigV1;
8616
+ runHandle?: RefillRunHandleV1;
8617
+ refillReporting?: Record<string, unknown>;
8618
+ conflicts?: undefined;
8619
+ } | {
8620
+ runSnapshot: unknown;
8621
+ readOnly: boolean;
8622
+ forbiddenActions: string[];
8623
+ boundedAuthority: string;
8624
+ status: "terminal";
8625
+ doneReason: string;
8626
+ report: Record<string, unknown>;
8627
+ runId: string;
8628
+ guidance?: string;
8629
+ journalPath?: string | null;
8630
+ targetConfig?: RefillTargetConfigV1;
8631
+ runHandle?: RefillRunHandleV1;
8632
+ refillReporting?: Record<string, unknown>;
8633
+ runState?: Record<string, unknown>;
8634
+ blocker?: undefined;
8635
+ conflicts?: undefined;
8636
+ };
8637
+ backgroundJob: {
8638
+ jobId: string;
8639
+ status?: undefined;
8640
+ activityState?: undefined;
8641
+ checkedRows?: undefined;
8642
+ preparedMessages?: undefined;
8643
+ activeCellCount?: undefined;
8644
+ };
8645
+ waitAction?: undefined;
8646
+ exactTargetPlan?: undefined;
8647
+ note?: undefined;
8648
+ handBack?: undefined;
8649
+ };
8650
+ continuation: {
8651
+ required: boolean;
8652
+ kind: string;
8653
+ owner: string;
8654
+ userActionRequired: boolean;
8655
+ tool: string;
8656
+ retryAfterMs: number;
8657
+ arguments: {
8658
+ workspaceRunState?: Record<string, unknown> | {
8659
+ coordinatorBlockedExactTargets: (Record<string, unknown> | null)[];
8660
+ } | undefined;
8661
+ yolo: boolean;
8662
+ executionMode: "yolo";
8663
+ requireWorkspace: boolean;
8664
+ workspaceId: string;
8665
+ workspaceCoordinator: boolean;
8666
+ backgroundWait: {
8667
+ jobId: string;
8668
+ campaignId: string;
8669
+ tableId: string;
8670
+ deadlineAt: string;
8671
+ };
8672
+ senders?: string[];
8673
+ senderIds?: string[];
8674
+ senderNames?: string[];
8675
+ horizonSendDays?: number;
8676
+ untilDate?: string;
8677
+ targetDate?: string;
8678
+ campaignId?: string;
8679
+ tableId?: string;
8680
+ intent?: RefillSendsIntent;
8681
+ approvalMode?: RefillSendsApprovalMode;
8682
+ actionTypes?: RefillSendsActionType[];
8683
+ expectedTargetShapeRevision?: string;
8684
+ expectedActionKey?: string;
8685
+ runId?: string;
8686
+ fence?: number;
8687
+ runHandle?: RefillRunHandleV1;
8688
+ targetConfig?: RefillTargetConfigV1;
8689
+ reportingContext?: RefillReportingContextV2;
8690
+ messageTemplateRevision?: MessageTemplateRevisionV1;
8691
+ agentKeywords?: string[];
8692
+ };
8693
+ stopCondition: string;
8694
+ renderBeforeInvoke?: undefined;
8695
+ };
8696
+ targetDate: string | null;
8697
+ untilDate: string | null;
8698
+ horizonSendDays: number | null;
8699
+ fillWindow: {
8700
+ mode: string;
8701
+ targetDate: string;
8702
+ description: string;
8703
+ untilDate?: undefined;
8704
+ horizonSendDays?: undefined;
8705
+ horizonHours?: undefined;
8706
+ } | {
8707
+ mode: string;
8708
+ untilDate: string;
8709
+ description: string;
8710
+ targetDate?: undefined;
8711
+ horizonSendDays?: undefined;
8712
+ horizonHours?: undefined;
8713
+ } | {
8714
+ mode: string;
8715
+ horizonSendDays: number | null;
8716
+ horizonHours: number | null;
8717
+ description: string;
8718
+ targetDate?: undefined;
8719
+ untilDate?: undefined;
8720
+ };
8721
+ approvalMode: RefillSendsApprovalMode;
8722
+ campaignId: string | null;
8723
+ tableId: string | null;
8724
+ targetConfig: RefillTargetConfigV1 | null;
8725
+ runHandle: RefillRunHandleV1 | null;
8726
+ reportingContext: RefillReportingContextV2 | null;
8727
+ messageTemplateRevision: MessageTemplateRevisionV1 | null;
8728
+ senderScope: string;
8729
+ senderSelectors: {
8730
+ senders: string[];
8731
+ senderIds: string[];
8732
+ senderNames: string[];
8733
+ };
8734
+ firstOperationalSteps: string[];
8735
+ approvalContract: string;
8736
+ forbiddenActions: string[];
8737
+ hostExamples: {
8738
+ claude: string[];
8739
+ codex: string[];
8740
+ mcpTool: {
8741
+ name: string;
8742
+ arguments: {
8743
+ workspaceRunState?: Record<string, unknown> | undefined;
8744
+ workspaceCoordinator?: boolean | undefined;
8745
+ messageTemplateRevision?: MessageTemplateRevisionV1 | undefined;
8746
+ reportingContext?: RefillReportingContextV2 | undefined;
8747
+ targetConfig?: RefillTargetConfigV1 | undefined;
8748
+ runHandle?: RefillRunHandleV1 | undefined;
8749
+ fence?: number | undefined;
8750
+ runId?: string | undefined;
8751
+ expectedActionKey?: string | undefined;
8752
+ expectedTargetShapeRevision?: string | undefined;
8753
+ targetDate: string | null;
8754
+ untilDate: string | null;
8755
+ horizonSendDays: number | null;
8756
+ campaignId: string | undefined;
8757
+ tableId: string | undefined;
8758
+ intent: RefillSendsIntent;
8759
+ approvalMode: RefillSendsApprovalMode;
8760
+ workspaceId: string | null;
8761
+ actionTypes?: ("send_invite" | "send_inmail_closed")[] | undefined;
8762
+ yolo: boolean;
8763
+ senders: string[];
8764
+ senderIds: string[];
8765
+ senderNames: string[];
8766
+ };
8767
+ };
8768
+ };
8769
+ actionTypes?: ("send_invite" | "send_inmail_closed")[] | undefined;
8770
+ command: string;
8771
+ tool: string;
8772
+ promptName: string;
8773
+ workflowPromptName: string;
8774
+ workflowAsset: {
8775
+ subskillName: string;
8776
+ assetPath: string;
8777
+ expectedVersion: string;
8778
+ };
8779
+ yolo: boolean;
8780
+ executionMode: RefillSendsExecutionMode;
8781
+ workspaceId: string | null;
8782
+ workspaceResolution: string;
8783
+ intent: RefillSendsIntent;
8400
8784
  } | {
8401
8785
  status: "terminal";
8402
8786
  doneReason: "loaded_awaiting_scheduler";
@@ -219,6 +219,13 @@ function normalizeWorkspaceRunState(value) {
219
219
  if (entries.length > 0)
220
220
  attemptLedgers[key] = entries;
221
221
  }
222
+ // fix(112aj): preserve the continuation-level progress-or-settle counter across
223
+ // coordinator calls. Like the attempt ledgers above, stripping it here would
224
+ // reset the identical-active_exact_run replay count to 1 on every resume and the
225
+ // cap could never trip.
226
+ const activeExactRunProgress = recordValue(root.activeExactRunProgress);
227
+ const activeExactRunFingerprint = stringValue(activeExactRunProgress?.fingerprint);
228
+ const activeExactRunCount = numberValue(activeExactRunProgress?.count);
222
229
  return {
223
230
  version: 1,
224
231
  senderCursors,
@@ -226,6 +233,14 @@ function normalizeWorkspaceRunState(value) {
226
233
  passRates: [],
227
234
  coordinatorBlockedExactTargets,
228
235
  ...attemptLedgers,
236
+ ...(activeExactRunFingerprint && typeof activeExactRunCount === "number"
237
+ ? {
238
+ activeExactRunProgress: {
239
+ fingerprint: activeExactRunFingerprint,
240
+ count: activeExactRunCount,
241
+ },
242
+ }
243
+ : {}),
229
244
  };
230
245
  }
231
246
  const WORKSPACE_ATTEMPT_LEDGER_KEYS = [
@@ -813,6 +828,36 @@ function withKeywordsHandoffScope(result, scopedInput) {
813
828
  }
814
829
  const BACKGROUND_WAIT_FAST_PATH_TTL_MS = 10 * 60 * 1000;
815
830
  const BACKGROUND_WAIT_MIN_RETRY_MS = 5_000;
831
+ // fix(112aj): the continuation-level progress-or-settle contract (the same
832
+ // principle as the ag/af-c bypasses, applied one layer up). An identical
833
+ // active_exact_run continuation — the SAME fence resumed at the same gate /
834
+ // gateSeq / state / plan / shape revision with no observable coverage or effect
835
+ // advance — may not be re-invoked unboundedly. Clover t4 (fence 109, run
836
+ // cmrz49lii) resumed a broaden fence stuck at g2_execute 20× with a byte-stable
837
+ // runSnapshot (gate g2_execute, gateSeq 2, stateRev 36a1de45) — no product effect,
838
+ // no fresh handoff, no no_forward_progress — because the broaden's own attempt
839
+ // bookkeeping wobbles the run-loop's mortality signature. This coordinator bound
840
+ // counts identical active_exact_run resumes and, past the cap, returns an honest
841
+ // no_forward_progress terminal and settles the fence (no continuation, not
842
+ // re-spawned). A fence that IS advancing (any fingerprint field changes) resets
843
+ // the counter and resumes normally, unbounded.
844
+ const ACTIVE_EXACT_RUN_REPLAY_CAP = 3;
845
+ function activeExactRunProgressFingerprint(result) {
846
+ const snapshot = recordValue(result.runSnapshot);
847
+ const runId = stringValue(result.runId) ?? stringValue(snapshot?.runId);
848
+ const fence = numberValue(result.fence);
849
+ if (!runId || typeof fence !== "number" || !snapshot)
850
+ return null;
851
+ return [
852
+ runId,
853
+ String(fence),
854
+ stringValue(snapshot.gate) ?? "",
855
+ String(numberValue(snapshot.gateSeq) ?? ""),
856
+ stringValue(snapshot.stateRevision) ?? "",
857
+ stringValue(snapshot.planRevision) ?? "",
858
+ stringValue(snapshot.targetShapeRevision) ?? "",
859
+ ].join("|");
860
+ }
816
861
  // Action families whose successful exact terminal means NEW ROWS landed on
817
862
  // the campaign — invalidating any earlier complete/capped defer for it.
818
863
  const WORKSPACE_SUPPLY_ACTION_FAMILIES = new Set([
@@ -895,6 +940,51 @@ function backgroundWaitFromSelection(selection, now) {
895
940
  retryAfterMs,
896
941
  };
897
942
  }
943
+ // fix(112ai): extract a still-running bounded prep/approve job receipt from a
944
+ // just-completed exact run. When the census bypass admits a masked prepare/
945
+ // approve edge, the coordinator dispatches a bounded job and the exact run
946
+ // returns exact_action_complete with a preparationReceipt that is still RUNNING
947
+ // (terminal:false) — the job drains the lane ASYNC, so the actionable census is
948
+ // non-empty only because scanning has not finished. That in-flight job IS the
949
+ // queued supply behind a non-empty census, so the coordinator must wait on it
950
+ // (self-heal) rather than false-terminal actionable_supply_not_queued
951
+ // (sellable-t4 7-29: prepare_messages:7fc0766d dispatched job cmrz555uc scanning
952
+ // while 681 enrich rows sat in the census). A terminal:true receipt means the
953
+ // job already drained; that is NOT a wait case, and the normal terminal logic
954
+ // (which may legitimately block on residual, correctly-named conditions) runs.
955
+ function dispatchedRunningPrepReceipt(result, completedFamily) {
956
+ if (completedFamily !== "prepare_messages" &&
957
+ completedFamily !== "approve_messages") {
958
+ return null;
959
+ }
960
+ const r = recordValue(result);
961
+ if (stringValue(r?.status) !== "terminal")
962
+ return null;
963
+ if (stringValue(r?.doneReason) !== "exact_action_complete")
964
+ return null;
965
+ const receipt = recordValue(recordValue(r?.report)?.preparationReceipt);
966
+ if (!receipt)
967
+ return null;
968
+ // Only a still-running durable receipt is draining work. terminal:true means
969
+ // the job finished (residual census is a different, correctly-named case); a
970
+ // failed/blocked/errored receipt is a real condition the terminal must surface.
971
+ if (receipt.terminal === true)
972
+ return null;
973
+ const status = stringValue(receipt.status);
974
+ if (status === "failed" ||
975
+ status === "error" ||
976
+ status === "blocked" ||
977
+ status === "cancelled") {
978
+ return null;
979
+ }
980
+ const jobId = stringValue(receipt.jobId);
981
+ if (!jobId)
982
+ return null;
983
+ return {
984
+ jobId,
985
+ retryAfterMs: Math.max(BACKGROUND_WAIT_MIN_RETRY_MS, numberValue(receipt.retryAfterMs) ?? 15_000),
986
+ };
987
+ }
898
988
  function workspaceExactTargetsFromAction(action) {
899
989
  if (!Array.isArray(action.exactTargets) || action.exactTargets.length === 0) {
900
990
  return [];
@@ -1458,6 +1548,24 @@ async function selectWorkspaceExactTarget(input, workspacePlanOverride, options
1458
1548
  selectedActionFamily === "continue_prospeo_source" ||
1459
1549
  selectedActionFamily === "broaden_provider_search" ||
1460
1550
  selectedActionFamily === "refresh_sender_post_engagers";
1551
+ // fix(112af-c/112ai): a prepare_messages OR approve_messages edge suffers the
1552
+ // same pooled-cascade masking as sources/sweeps/waits — its exact scope can
1553
+ // read scheduler-loaded or complete via the shared ready buffer while the lane
1554
+ // still holds genuine actionable supply (sellable.dev 7-29: cmrcd4x4a
1555
+ // send_invite prepare skipped while 69 enrich + 1 generate never-run rows sat
1556
+ // behind it; Amplify t3 Sadhna + Dotwork cmqbt8b8: approve_messages skipped
1557
+ // while a real approval frontier — needsApproval > 0 — sat behind it). This
1558
+ // closes the masked-supply family (sweep→112ag, prepare→112af-c, approve→112ai)
1559
+ // with ONE census-conditional bypass. Unlike sources/sweeps/waits these are not
1560
+ // unconditionally bindable — a genuinely-complete prepare/approve must stay
1561
+ // deferred to avoid a re-prepare loop. So bind ONLY when the LANE-SCOPED
1562
+ // actionable census (per-sender existingRowFrontier stageCounts —
1563
+ // needsApproval/needsGenerate/needsEnrich/needsRubric, never the pooled
1564
+ // coverage) proves a real frontier; an empty census keeps the settled skip, and
1565
+ // the bounded job consumes the frontier so the census drains.
1566
+ const isMaskedSupplyTarget = (selectedActionFamily === "prepare_messages" ||
1567
+ selectedActionFamily === "approve_messages") &&
1568
+ exactPlanHasLaneScopedActionableFrontier(exactTargetPlan);
1461
1569
  // fix(111f, OWNER DIRECTIVE — dispatch-first): a settled preflight read
1462
1570
  // may only skip a target when its exact plan exposes NO unresolved
1463
1571
  // coordinator action — any bindable head (source supply, sweeps,
@@ -1470,6 +1578,7 @@ async function selectWorkspaceExactTarget(input, workspacePlanOverride, options
1470
1578
  const bypassSettledSkips = isSchedulerSweepTarget ||
1471
1579
  isBackgroundWaitTarget ||
1472
1580
  isSourceSupplyTarget ||
1581
+ isMaskedSupplyTarget ||
1473
1582
  yoloPlanHasUnresolvedCoordinatorAction(exactTargetPlan);
1474
1583
  if (!bypassSettledSkips && yoloPlanIsComplete(exactTargetPlan)) {
1475
1584
  completedExactTargetCount += 1;
@@ -1786,6 +1895,27 @@ function classifyWorkspaceUnavailableTerminal(plan, contextNote) {
1786
1895
  }
1787
1896
  return { code: "workspace_exact_target_unavailable", note: contextNote };
1788
1897
  }
1898
+ // fix(112af-c/112ai): a prepare_messages OR approve_messages edge on a cascade can
1899
+ // read scheduler-loaded or complete at the pooled campaign scope (the shared ready
1900
+ // buffer routed to Open/paid InMail or the connection fallback covers the aggregate
1901
+ // gap) while a specific lane still holds genuine actionable supply the pooled
1902
+ // coverage masks (sellable.dev 7-29: cmrcd4x4a send_invite prepare skipped as
1903
+ // "complete or scheduler-loaded" while 69 enrich + 1 generate never-run rows sat
1904
+ // behind it; Dotwork cmqbt8b8 + Amplify t3 Sadhna: approve skipped while a real
1905
+ // needsApproval frontier sat behind it). The lane-scoped signal is the per-sender
1906
+ // existingRowFrontier stageCounts summed by workspaceActionableSupplyCensus — NEVER
1907
+ // the pooled readyBuffer/coverage. When that census is non-empty the edge is a
1908
+ // masked-gap prep/approve and must bind so the bounded job consumes the frontier;
1909
+ // when the census is empty the edge is genuinely settled and stays deferred (no
1910
+ // re-prepare / re-approve loop).
1911
+ function exactPlanHasLaneScopedActionableFrontier(plan) {
1912
+ const census = workspaceActionableSupplyCensus(plan);
1913
+ return (census.approvalFrontier > 0 ||
1914
+ census.generateFrontier > 0 ||
1915
+ census.enrichFrontier > 0 ||
1916
+ census.rubricFrontier > 0 ||
1917
+ census.frontierHasMoreRows);
1918
+ }
1789
1919
  function yoloPlanIsComplete(plan) {
1790
1920
  const coverage = yoloCoverage(plan);
1791
1921
  return (coverage.status === "complete" ||
@@ -3381,6 +3511,49 @@ export async function executeRefillSendsCommand(input = {}) {
3381
3511
  : supplyLandedOnCampaign
3382
3512
  ? clearCompleteDefersForCampaign(deferredCoordinatorWorkspaceRunState, selectedCoordinatorTarget?.campaignId ?? null)
3383
3513
  : deferredCoordinatorWorkspaceRunState;
3514
+ // fix(112aj): continuation-level progress-or-settle. When this dispatch is an
3515
+ // active_exact_run resume (continuationHandle set, in_progress), fingerprint
3516
+ // the fence's observable state; if the SAME fence has been re-invoked
3517
+ // ACTIVE_EXACT_RUN_REPLAY_CAP times with a byte-identical fingerprint (no
3518
+ // coverage/effect advance), settle it honestly instead of re-inviting an
3519
+ // identical continuation. A fence that advanced (any fingerprint field moved)
3520
+ // resets the counter and resumes normally.
3521
+ let progressBoundedWorkspaceRunState = coordinatorWorkspaceRunState;
3522
+ if (yolo && continuationHandle) {
3523
+ const fingerprint = activeExactRunProgressFingerprint(result);
3524
+ const priorProgress = recordValue(recordValue(scopedInput.workspaceRunState)?.activeExactRunProgress);
3525
+ const replayCount = fingerprint && stringValue(priorProgress?.fingerprint) === fingerprint
3526
+ ? (numberValue(priorProgress?.count) ?? 0) + 1
3527
+ : 1;
3528
+ if (fingerprint && replayCount >= ACTIVE_EXACT_RUN_REPLAY_CAP) {
3529
+ return {
3530
+ ...command,
3531
+ ok: false,
3532
+ status: "blocked",
3533
+ blocker: "no_forward_progress",
3534
+ note: `The active exact run (${continuationHandle.runId} fence ${continuationHandle.fence}) was resumed ${replayCount} times with no observable coverage or effect advance ` +
3535
+ "(identical gate/state fingerprint). Settling the fence instead of re-inviting an identical continuation; a fresh refill_sends command reconciles it. No run or mutation was started.",
3536
+ coordinator: {
3537
+ scope: "workspace",
3538
+ status: "blocked",
3539
+ },
3540
+ continuation: { required: false, userActionRequired: false },
3541
+ };
3542
+ }
3543
+ progressBoundedWorkspaceRunState = fingerprint
3544
+ ? {
3545
+ ...(recordValue(coordinatorWorkspaceRunState) ?? {}),
3546
+ activeExactRunProgress: { fingerprint, count: replayCount },
3547
+ }
3548
+ : coordinatorWorkspaceRunState;
3549
+ }
3550
+ else {
3551
+ const base = recordValue(coordinatorWorkspaceRunState);
3552
+ if (base && "activeExactRunProgress" in base) {
3553
+ const { activeExactRunProgress: _cleared, ...rest } = base;
3554
+ progressBoundedWorkspaceRunState = rest;
3555
+ }
3556
+ }
3384
3557
  const workspaceContinuationArguments = {
3385
3558
  yolo: true,
3386
3559
  executionMode: "yolo",
@@ -3400,8 +3573,8 @@ export async function executeRefillSendsCommand(input = {}) {
3400
3573
  : {}),
3401
3574
  approvalMode: scopedInput.approvalMode ?? "approve",
3402
3575
  ...(isWorkspaceCoordinator ? { workspaceCoordinator: true } : {}),
3403
- ...(coordinatorWorkspaceRunState
3404
- ? { workspaceRunState: coordinatorWorkspaceRunState }
3576
+ ...(progressBoundedWorkspaceRunState
3577
+ ? { workspaceRunState: progressBoundedWorkspaceRunState }
3405
3578
  : {}),
3406
3579
  };
3407
3580
  if (isWorkspaceCoordinator &&
@@ -3627,6 +3800,79 @@ export async function executeRefillSendsCommand(input = {}) {
3627
3800
  };
3628
3801
  }
3629
3802
  if (nextSelection.status === "blocked") {
3803
+ // fix(112ai, OWNER closing invariant): actionable_supply_not_queued is a
3804
+ // planner-exposure DEFECT terminal and is legal ONLY when no bounded
3805
+ // prep/approve job dispatched THIS command is still draining the census.
3806
+ // The af-c/ai census bypass admits the masked prepare/approve edge and
3807
+ // the coordinator dispatches a bounded job, but that job drains ASYNC:
3808
+ // the exact run returns exact_action_complete with a still-running
3809
+ // receipt (terminal:false) while the census still shows the un-drained
3810
+ // rows. Emitting actionable_supply_not_queued here (continuation
3811
+ // required:false) HALTS the yolo loop before the job drains — the exact
3812
+ // false-terminal the owner ruled unacceptable on sellable-t4
3813
+ // (prepare_messages:7fc0766d dispatched job cmrz555uc scanning while 681
3814
+ // enrich rows sat in the census). Recognize the in-flight job as the
3815
+ // queued supply: emit a healthy background-wait so the loop re-invokes,
3816
+ // the fast path probes the job by id (sidestepping the planner-exposure
3817
+ // gap that starved the reread), and the census drains (self-heal). This
3818
+ // makes "non-empty census + dispatched running job + halting defect
3819
+ // terminal" unrepresentable.
3820
+ const runningPrepReceipt = dispatchedRunningPrepReceipt(result, completedPrepFamily);
3821
+ if (nextSelection.code === "actionable_supply_not_queued" &&
3822
+ runningPrepReceipt &&
3823
+ selectedCoordinatorTarget) {
3824
+ const backgroundContinuationInput = workspaceCoordinatorInput(scopedInput);
3825
+ delete backgroundContinuationInput.expectedTargetShapeRevision;
3826
+ delete backgroundContinuationInput.expectedActionKey;
3827
+ const backgroundWait = {
3828
+ jobId: runningPrepReceipt.jobId,
3829
+ campaignId: selectedCoordinatorTarget.campaignId ?? null,
3830
+ tableId: selectedCoordinatorTarget.tableId ?? null,
3831
+ deadlineAt: new Date(Date.now() + BACKGROUND_WAIT_FAST_PATH_TTL_MS).toISOString(),
3832
+ };
3833
+ return {
3834
+ ...command,
3835
+ status: "in_progress",
3836
+ note: `The exact ${completedPrepFamily} edge dispatched a bounded preparation job (${runningPrepReceipt.jobId}) that is still draining the lane; the actionable census remains non-empty only because that job has not finished scanning. Waiting on the in-flight job instead of false-terminaling actionable_supply_not_queued — the loop re-invokes, the job drains the frontier, and coverage advances.`,
3837
+ targetPlan: nextSelection.workspacePlan,
3838
+ exactTargetPlan: nextSelection.exactTargetPlan ?? null,
3839
+ orchestration: {
3840
+ mode: "fenced_bounded_yolo",
3841
+ scope: "workspace_exact_target_coordinator",
3842
+ phase: "read_only_background_wait",
3843
+ },
3844
+ coordinator: {
3845
+ scope: "workspace",
3846
+ status: "waiting_background",
3847
+ completedTarget: selectedCoordinatorTarget,
3848
+ selectedTarget: selectedCoordinatorTarget,
3849
+ workspaceTargetPlan: nextSelection.workspacePlan,
3850
+ exactRunResult: result,
3851
+ backgroundJob: { jobId: runningPrepReceipt.jobId },
3852
+ },
3853
+ continuation: {
3854
+ required: true,
3855
+ kind: "workspace_background_wait",
3856
+ owner: "packaged_workflow",
3857
+ userActionRequired: false,
3858
+ tool: "refill_sends",
3859
+ retryAfterMs: runningPrepReceipt.retryAfterMs,
3860
+ arguments: {
3861
+ ...backgroundContinuationInput,
3862
+ yolo: true,
3863
+ executionMode: "yolo",
3864
+ requireWorkspace: true,
3865
+ workspaceId,
3866
+ workspaceCoordinator: true,
3867
+ backgroundWait,
3868
+ ...(coordinatorWorkspaceRunState
3869
+ ? { workspaceRunState: coordinatorWorkspaceRunState }
3870
+ : {}),
3871
+ },
3872
+ stopCondition: "A bounded preparation job dispatched this command is still draining the actionable census. After the bounded wait, replan the whole workspace; do not open or resume an exact fence solely to poll background work.",
3873
+ },
3874
+ };
3875
+ }
3630
3876
  const persistedDeferredBlocker = coordinatorDeferredBlocker(coordinatorWorkspaceRunState);
3631
3877
  const workspaceCoverage = yoloCoverage(nextSelection.workspacePlan);
3632
3878
  if (persistedDeferredBlocker === "loaded_awaiting_scheduler" &&
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/mcp",
3
- "version": "0.1.729",
3
+ "version": "0.1.731",
4
4
  "type": "module",
5
5
  "description": "Sellable MCP server for Claude Code, Codex, and Hermes campaign workflows",
6
6
  "main": "dist/index.js",