@sellable/mcp 0.1.741 → 0.1.743
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.
|
@@ -176,14 +176,12 @@ declare function coverageOnlySignature(plan: Record<string, unknown>): {
|
|
|
176
176
|
sent: number;
|
|
177
177
|
scheduled: number;
|
|
178
178
|
ready: number;
|
|
179
|
-
goal: number;
|
|
180
179
|
};
|
|
181
180
|
declare function nextCoverageStallState(ctx: LoopContext, plan: Record<string, unknown>): {
|
|
182
181
|
signature: {
|
|
183
182
|
sent: number;
|
|
184
183
|
scheduled: number;
|
|
185
184
|
ready: number;
|
|
186
|
-
goal: number;
|
|
187
185
|
};
|
|
188
186
|
repeatCount: number;
|
|
189
187
|
};
|
package/dist/refill-run-loop.js
CHANGED
|
@@ -1889,11 +1889,17 @@ function nextNoProgressState(ctx, plan, action) {
|
|
|
1889
1889
|
const COVERAGE_STALL_LIMIT = 6;
|
|
1890
1890
|
function coverageOnlySignature(plan) {
|
|
1891
1891
|
const coverage = coverageSnapshot(plan);
|
|
1892
|
+
// fix(112an-b): PROGRESS counters only — deliberately NOT `goal`.
|
|
1893
|
+
// Live Dotwork on 0.1.740 ran 28 exact runs with sent/scheduled/ready frozen at
|
|
1894
|
+
// 0/0/20 while `goal` alternated 50 <-> 40 as the planner rescoped its sender
|
|
1895
|
+
// set. Including goal made the signature change every iteration, reset the
|
|
1896
|
+
// streak, and the bound never reached COVERAGE_STALL_LIMIT — 61 calls and
|
|
1897
|
+
// still going. goal is a TARGET, not progress: if sent/scheduled/ready are
|
|
1898
|
+
// frozen the command is stalled no matter what the target says.
|
|
1892
1899
|
return {
|
|
1893
1900
|
sent: coverage.sent,
|
|
1894
1901
|
scheduled: coverage.scheduled,
|
|
1895
1902
|
ready: coverage.ready,
|
|
1896
|
-
goal: coverage.goal,
|
|
1897
1903
|
};
|
|
1898
1904
|
}
|
|
1899
1905
|
function nextCoverageStallState(ctx, plan) {
|
|
@@ -2727,8 +2733,8 @@ async function gatePlan(input, deps, ctx) {
|
|
|
2727
2733
|
progress: { coverageStall },
|
|
2728
2734
|
coverage: frozen,
|
|
2729
2735
|
guidance: `Coverage did not move across ${COVERAGE_STALL_LIMIT} consecutive refill iterations ` +
|
|
2730
|
-
`(sent ${frozen.sent}, scheduled ${frozen.scheduled}, ready ${frozen.ready}
|
|
2731
|
-
|
|
2736
|
+
`(sent ${frozen.sent}, scheduled ${frozen.scheduled}, ready ${frozen.ready}); ` +
|
|
2737
|
+
"the actions differed each time, so this is a workspace-level " +
|
|
2732
2738
|
"stall rather than one repeated rung. Settling instead of continuing to spend. " +
|
|
2733
2739
|
"Re-run after the underlying blocker changes; the last attempted action is reported above.",
|
|
2734
2740
|
});
|
|
@@ -214,7 +214,7 @@ export type SchedulerChangedCounts = {
|
|
|
214
214
|
}>;
|
|
215
215
|
};
|
|
216
216
|
export declare function normalizeSchedulerChangedCounts(value: unknown): SchedulerChangedCounts | null;
|
|
217
|
-
export declare function schedulerEnvelopeIsTerminal(schedulerStatus: string): boolean;
|
|
217
|
+
export declare function schedulerEnvelopeIsTerminal(schedulerStatus: string, receipt?: Record<string, unknown> | null): boolean;
|
|
218
218
|
export declare function normalizeSchedulerPrimitiveResult(value: unknown, expected?: {
|
|
219
219
|
expectedTargets: SchedulerExpectedTargetInput[];
|
|
220
220
|
expectedTargetsHash: string;
|
|
@@ -223,7 +223,7 @@ export declare function normalizeSchedulerPrimitiveResult(value: unknown, expect
|
|
|
223
223
|
retryAfterMs: number;
|
|
224
224
|
changedCounts: null;
|
|
225
225
|
auditComplete: false;
|
|
226
|
-
|
|
226
|
+
unsettledReceipt?: Record<string, unknown> | undefined;
|
|
227
227
|
status: "matching_scheduler_active";
|
|
228
228
|
schedulerStatus: string;
|
|
229
229
|
terminal: false;
|
|
@@ -274,50 +274,71 @@ function completeExpectedTargetSummary(value, expectedTargets, maxPlacements) {
|
|
|
274
274
|
JSON.stringify(accounted) === JSON.stringify(target?.senderIds));
|
|
275
275
|
});
|
|
276
276
|
}
|
|
277
|
-
// fix(112ao-2): the scheduler's
|
|
278
|
-
//
|
|
279
|
-
//
|
|
280
|
-
const
|
|
281
|
-
// The envelope statuses that report
|
|
282
|
-
// therefore eligible for the receipt audit below.
|
|
277
|
+
// fix(112ao-2): the scheduler's ATTACHING envelope statuses. These describe a
|
|
278
|
+
// dispatch that joined an existing run rather than producing its own outcome.
|
|
279
|
+
// They are terminal ONLY when the attach actually yielded a terminal receipt.
|
|
280
|
+
const SCHEDULER_ATTACHING_ENVELOPE_STATUSES = new Set(["accepted", "attached"]);
|
|
281
|
+
// The envelope statuses that report an outcome of this dispatch directly.
|
|
283
282
|
const SCHEDULER_TERMINAL_ENVELOPE_STATUSES = new Set([
|
|
284
283
|
"ran",
|
|
285
284
|
"window_closed_noop",
|
|
286
285
|
]);
|
|
287
|
-
|
|
288
|
-
|
|
286
|
+
// The only receipt statuses that constitute a settled outcome. A receipt
|
|
287
|
+
// without one of these is not evidence that anything finished.
|
|
288
|
+
const SCHEDULER_TERMINAL_RECEIPT_STATUSES = new Set([
|
|
289
|
+
"ran",
|
|
290
|
+
"window_closed_noop",
|
|
291
|
+
"failed",
|
|
292
|
+
]);
|
|
293
|
+
function hasTerminalSchedulerReceipt(receipt) {
|
|
294
|
+
const status = receipt ? stringValue(receipt.status) : null;
|
|
295
|
+
return Boolean(status && SCHEDULER_TERMINAL_RECEIPT_STATUSES.has(status));
|
|
296
|
+
}
|
|
297
|
+
export function schedulerEnvelopeIsTerminal(schedulerStatus, receipt = null) {
|
|
298
|
+
if (SCHEDULER_TERMINAL_ENVELOPE_STATUSES.has(schedulerStatus))
|
|
299
|
+
return true;
|
|
300
|
+
return (SCHEDULER_ATTACHING_ENVELOPE_STATUSES.has(schedulerStatus) &&
|
|
301
|
+
hasTerminalSchedulerReceipt(receipt));
|
|
289
302
|
}
|
|
290
303
|
export function normalizeSchedulerPrimitiveResult(value, expected) {
|
|
291
304
|
const response = recordValue(value);
|
|
292
305
|
const receipt = recordValue(response?.receipt);
|
|
293
306
|
const schedulerStatus = stringValue(response?.status) ?? stringValue(receipt?.status) ?? "unknown";
|
|
294
307
|
const errorCode = stringValue(recordValue(response?.error)?.code);
|
|
295
|
-
// fix(112ao-2): whether this dispatch finished is
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
// depend on whether a field happened to be present: the scheduler may attach
|
|
299
|
-
// an in-flight response to an already-running job and replay THAT job's
|
|
300
|
-
// receipt, so an `attached` envelope arrived carrying complete, v3-auditable
|
|
301
|
-
// counters from a prior run. It skipped this branch, passed the audit on
|
|
302
|
-
// that stale evidence, and returned auditComplete: true — the coordinator
|
|
303
|
-
// read a finished sweep and redispatched the run it should have awaited
|
|
304
|
-
// (Dotwork 2026-07-29: 21 exact runs, coverage frozen at sent:0/scheduled:0).
|
|
308
|
+
// fix(112ao-2): whether this dispatch finished is decided explicitly from the
|
|
309
|
+
// envelope status plus the RECEIPT'S OWN STATUS — never from the bare
|
|
310
|
+
// presence of a receipt field.
|
|
305
311
|
//
|
|
306
|
-
//
|
|
307
|
-
//
|
|
312
|
+
// The previous guard was `!receipt && (accepted || attached)`. Truthiness is
|
|
313
|
+
// the wrong test: an attach that carries a receipt with no terminal status is
|
|
314
|
+
// not evidence that anything settled, yet it skipped this branch, ran the v3
|
|
315
|
+
// audit on that non-evidence, and could return auditComplete: true — a
|
|
316
|
+
// completion claim for a run still in flight, which the coordinator then
|
|
317
|
+
// treats as done rather than awaiting (Dotwork 2026-07-29: 21 exact runs,
|
|
318
|
+
// coverage frozen at sent:0/scheduled:0).
|
|
319
|
+
//
|
|
320
|
+
// The attach is NOT always in flight, and this deliberately does not treat it
|
|
321
|
+
// so: scheduler-run.ts:466-483 only returns a receipt from
|
|
322
|
+
// waitForSchedulerRunReceipt when it is scope-matched to THIS request, so an
|
|
323
|
+
// attach carrying a terminal receipt is a legitimate idempotent completion of
|
|
324
|
+
// this exact operation and must keep its counters. Discarding it would report
|
|
325
|
+
// zero placements for a sweep that really placed cells.
|
|
326
|
+
//
|
|
327
|
+
// `ran`/`window_closed_noop` remain terminal. `backoff`/`failed` keep their
|
|
308
328
|
// existing handling — the run loop already unwraps a backoff envelope's
|
|
309
329
|
// replayed receipt deliberately (schedulerRunReceiptIsFreshZeroScheduled).
|
|
310
|
-
if (
|
|
330
|
+
if (SCHEDULER_ATTACHING_ENVELOPE_STATUSES.has(schedulerStatus) &&
|
|
331
|
+
!hasTerminalSchedulerReceipt(receipt)) {
|
|
311
332
|
return {
|
|
312
333
|
status: "matching_scheduler_active",
|
|
313
334
|
schedulerStatus,
|
|
314
335
|
terminal: false,
|
|
315
336
|
disposition: "bounded_reread_wait",
|
|
316
337
|
receipt: null,
|
|
317
|
-
// A
|
|
318
|
-
//
|
|
319
|
-
//
|
|
320
|
-
...(receipt ? {
|
|
338
|
+
// A non-terminal receipt is not this dispatch's effect. Surfaced under a
|
|
339
|
+
// distinct name so it stays readable for diagnostics but can never be
|
|
340
|
+
// mistaken for a settled outcome.
|
|
341
|
+
...(receipt ? { unsettledReceipt: receipt } : {}),
|
|
321
342
|
retryAfterMs: numberValue(response?.retryAfterMs) ?? 30_000,
|
|
322
343
|
changedCounts: null,
|
|
323
344
|
auditComplete: false,
|
|
@@ -363,7 +384,7 @@ export function normalizeSchedulerPrimitiveResult(value, expected) {
|
|
|
363
384
|
status: schedulerStatus,
|
|
364
385
|
// fix(112ao-2): the completion decision, carried explicitly instead of
|
|
365
386
|
// leaving each consumer to re-infer it from the status string.
|
|
366
|
-
terminal: schedulerEnvelopeIsTerminal(schedulerStatus),
|
|
387
|
+
terminal: schedulerEnvelopeIsTerminal(schedulerStatus, receipt),
|
|
367
388
|
receipt: response?.receipt ?? null,
|
|
368
389
|
retryAfterMs: numberValue(response?.retryAfterMs),
|
|
369
390
|
changedCounts,
|
|
@@ -2967,14 +2988,19 @@ export async function executeOneYoloPrimitive(action, workspaceId) {
|
|
|
2967
2988
|
refusalReason: "run_scheduler_sweep action is missing exact workspace/date/revision scope or complete receipt requirements",
|
|
2968
2989
|
};
|
|
2969
2990
|
}
|
|
2991
|
+
// fix(112ao-1): poll by RUN IDENTITY. requestKey is already unique per
|
|
2992
|
+
// sweep, so requestKey + targetDate names this exact dispatch. Sending
|
|
2993
|
+
// targetShapeRevision/expectedTargetsHash/maxPlacements here made the
|
|
2994
|
+
// probe assert that the PLANNER's revision had not moved — but it is
|
|
2995
|
+
// state-fresh by design (112q D2), so it always had, scopeMatches came
|
|
2996
|
+
// back false, and every wait branch below fell through to the
|
|
2997
|
+
// action:"run" redispatch at the end of this block. The dispatch below
|
|
2998
|
+
// still carries the full write scope.
|
|
2970
2999
|
const statusResult = recordValue(await runSchedulerSweep({
|
|
2971
3000
|
workspaceId,
|
|
2972
3001
|
action: "status",
|
|
2973
3002
|
targetDate,
|
|
2974
3003
|
requestKey,
|
|
2975
|
-
targetShapeRevision,
|
|
2976
|
-
expectedTargetsHash,
|
|
2977
|
-
maxPlacements,
|
|
2978
3004
|
}));
|
|
2979
3005
|
const statusErrorCode = stringValue(recordValue(statusResult?.lastError)?.code);
|
|
2980
3006
|
if (statusResult?.scopeMatches === true &&
|