@sellable/mcp 0.1.794 → 0.1.795
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.
- package/dist/tools/campaign-processing.d.ts +18 -0
- package/dist/tools/campaign-processing.js +19 -2
- package/dist/tools/integrations.d.ts +4 -4
- package/dist/tools/integrations.js +26 -5
- package/dist/tools/registry.d.ts +8 -0
- package/package.json +1 -1
- package/skills/refill-sends/SKILL.md +11 -2
- package/skills/refill-sends-workflow/SKILL.md +12 -4
- package/skills/refill-sends-workflow/core/flow.v3.json +26 -37
|
@@ -493,6 +493,8 @@ type WaitInput = SchemaInput & {
|
|
|
493
493
|
minPassedCount?: number;
|
|
494
494
|
minGeneratedMessages?: number;
|
|
495
495
|
templateRevision?: "current" | string;
|
|
496
|
+
/** Wait until the exact campaign table has no queued or processing cells. */
|
|
497
|
+
requireIdle?: boolean;
|
|
496
498
|
timeoutMs?: number;
|
|
497
499
|
intervalMs?: number;
|
|
498
500
|
};
|
|
@@ -577,6 +579,7 @@ export declare const campaignProcessingToolDefinitions: ({
|
|
|
577
579
|
minPassedCount?: undefined;
|
|
578
580
|
minGeneratedMessages?: undefined;
|
|
579
581
|
templateRevision?: undefined;
|
|
582
|
+
requireIdle?: undefined;
|
|
580
583
|
timeoutMs?: undefined;
|
|
581
584
|
intervalMs?: undefined;
|
|
582
585
|
rowIds?: undefined;
|
|
@@ -654,6 +657,7 @@ export declare const campaignProcessingToolDefinitions: ({
|
|
|
654
657
|
minPassedCount?: undefined;
|
|
655
658
|
minGeneratedMessages?: undefined;
|
|
656
659
|
templateRevision?: undefined;
|
|
660
|
+
requireIdle?: undefined;
|
|
657
661
|
timeoutMs?: undefined;
|
|
658
662
|
intervalMs?: undefined;
|
|
659
663
|
rowIds?: undefined;
|
|
@@ -721,6 +725,7 @@ export declare const campaignProcessingToolDefinitions: ({
|
|
|
721
725
|
minPassedCount?: undefined;
|
|
722
726
|
minGeneratedMessages?: undefined;
|
|
723
727
|
templateRevision?: undefined;
|
|
728
|
+
requireIdle?: undefined;
|
|
724
729
|
timeoutMs?: undefined;
|
|
725
730
|
intervalMs?: undefined;
|
|
726
731
|
rowIds?: undefined;
|
|
@@ -757,6 +762,9 @@ export declare const campaignProcessingToolDefinitions: ({
|
|
|
757
762
|
type: string;
|
|
758
763
|
description: string;
|
|
759
764
|
};
|
|
765
|
+
requireIdle: {
|
|
766
|
+
type: string;
|
|
767
|
+
};
|
|
760
768
|
timeoutMs: {
|
|
761
769
|
type: string;
|
|
762
770
|
};
|
|
@@ -814,6 +822,7 @@ export declare const campaignProcessingToolDefinitions: ({
|
|
|
814
822
|
minPassedCount?: undefined;
|
|
815
823
|
minGeneratedMessages?: undefined;
|
|
816
824
|
templateRevision?: undefined;
|
|
825
|
+
requireIdle?: undefined;
|
|
817
826
|
timeoutMs?: undefined;
|
|
818
827
|
intervalMs?: undefined;
|
|
819
828
|
targetConfig?: undefined;
|
|
@@ -1035,6 +1044,7 @@ export declare const campaignProcessingToolDefinitions: ({
|
|
|
1035
1044
|
minPassedCount?: undefined;
|
|
1036
1045
|
minGeneratedMessages?: undefined;
|
|
1037
1046
|
templateRevision?: undefined;
|
|
1047
|
+
requireIdle?: undefined;
|
|
1038
1048
|
timeoutMs?: undefined;
|
|
1039
1049
|
intervalMs?: undefined;
|
|
1040
1050
|
rowIds?: undefined;
|
|
@@ -1067,6 +1077,7 @@ export declare function waitForCampaignProcessing(input: WaitInput): Promise<{
|
|
|
1067
1077
|
currentTemplateRevisionHash: string;
|
|
1068
1078
|
guidance: string;
|
|
1069
1079
|
stats: WorkflowTableStats;
|
|
1080
|
+
idle?: undefined;
|
|
1070
1081
|
floors?: undefined;
|
|
1071
1082
|
result?: undefined;
|
|
1072
1083
|
warning?: undefined;
|
|
@@ -1078,6 +1089,7 @@ export declare function waitForCampaignProcessing(input: WaitInput): Promise<{
|
|
|
1078
1089
|
elapsedMs: number;
|
|
1079
1090
|
tableId: string;
|
|
1080
1091
|
pollKey: string;
|
|
1092
|
+
idle: boolean;
|
|
1081
1093
|
floors: {
|
|
1082
1094
|
minPassedCount: number | null;
|
|
1083
1095
|
minGeneratedMessages: number | null;
|
|
@@ -1090,6 +1102,8 @@ export declare function waitForCampaignProcessing(input: WaitInput): Promise<{
|
|
|
1090
1102
|
staleGeneratedMessagesCount: number;
|
|
1091
1103
|
generatedWithoutPassCount: number;
|
|
1092
1104
|
currentTemplateRevisionHash: string | null;
|
|
1105
|
+
queuedCount: number | null;
|
|
1106
|
+
processingCount: number | null;
|
|
1093
1107
|
};
|
|
1094
1108
|
stats: WorkflowTableStats;
|
|
1095
1109
|
reason?: undefined;
|
|
@@ -1116,6 +1130,9 @@ export declare function waitForCampaignProcessing(input: WaitInput): Promise<{
|
|
|
1116
1130
|
currentTemplateRevisionHash: string | null;
|
|
1117
1131
|
passFloorMet: boolean;
|
|
1118
1132
|
generatedFloorMet: boolean;
|
|
1133
|
+
idle: boolean;
|
|
1134
|
+
queuedCount: number | null;
|
|
1135
|
+
processingCount: number | null;
|
|
1119
1136
|
};
|
|
1120
1137
|
recovery: {
|
|
1121
1138
|
checkpoint: string;
|
|
@@ -1146,6 +1163,7 @@ export declare function waitForCampaignProcessing(input: WaitInput): Promise<{
|
|
|
1146
1163
|
stats: WorkflowTableStats | null;
|
|
1147
1164
|
requestedTemplateRevision?: undefined;
|
|
1148
1165
|
currentTemplateRevisionHash?: undefined;
|
|
1166
|
+
idle?: undefined;
|
|
1149
1167
|
floors?: undefined;
|
|
1150
1168
|
result?: undefined;
|
|
1151
1169
|
}>;
|
|
@@ -434,7 +434,7 @@ export const campaignProcessingToolDefinitions = [
|
|
|
434
434
|
},
|
|
435
435
|
{
|
|
436
436
|
name: "wait_for_campaign_processing",
|
|
437
|
-
description: "Stats-only campaign processing wait. Use for fit/message readiness
|
|
437
|
+
description: "Stats-only campaign processing wait. Use for fit/message readiness or requireIdle:true when an exact campaign table must settle before replanning. Generated messages are counted separately from rubric passes; current template revision is enforced through messageDraftBasis.approvedBriefHash.",
|
|
438
438
|
inputSchema: {
|
|
439
439
|
type: "object",
|
|
440
440
|
properties: {
|
|
@@ -447,6 +447,7 @@ export const campaignProcessingToolDefinitions = [
|
|
|
447
447
|
type: "string",
|
|
448
448
|
description: '"current" (default when minGeneratedMessages is set) or an explicit current approved brief hash.',
|
|
449
449
|
},
|
|
450
|
+
requireIdle: { type: "boolean" },
|
|
450
451
|
timeoutMs: { type: "number" },
|
|
451
452
|
intervalMs: { type: "number" },
|
|
452
453
|
},
|
|
@@ -603,6 +604,7 @@ function buildProcessingTimeoutRecovery({ input, schema, stats, minPassedCount,
|
|
|
603
604
|
...(minPassedCount ? { minPassedCount } : {}),
|
|
604
605
|
...(minGeneratedMessages ? { minGeneratedMessages } : {}),
|
|
605
606
|
...(templateRevision ? { templateRevision } : {}),
|
|
607
|
+
...(input.requireIdle ? { requireIdle: true } : {}),
|
|
606
608
|
},
|
|
607
609
|
});
|
|
608
610
|
}
|
|
@@ -693,11 +695,13 @@ export async function waitForCampaignProcessing(input) {
|
|
|
693
695
|
: null;
|
|
694
696
|
const templateRevision = input.templateRevision ??
|
|
695
697
|
(minGeneratedMessages !== null ? "current" : null);
|
|
698
|
+
const requireIdle = input.requireIdle === true;
|
|
696
699
|
const pollKey = stableHash({
|
|
697
700
|
tableId: schema.tableId,
|
|
698
701
|
minPassedCount,
|
|
699
702
|
minGeneratedMessages,
|
|
700
703
|
templateRevision,
|
|
704
|
+
requireIdle,
|
|
701
705
|
});
|
|
702
706
|
const start = Date.now();
|
|
703
707
|
let attempts = 0;
|
|
@@ -732,13 +736,19 @@ export async function waitForCampaignProcessing(input) {
|
|
|
732
736
|
: (stats.generatedMessagesCount ?? stats.messagesCount ?? 0);
|
|
733
737
|
const passFloorMet = minPassedCount === null || passed >= minPassedCount;
|
|
734
738
|
const generatedFloorMet = minGeneratedMessages === null || generated >= minGeneratedMessages;
|
|
735
|
-
|
|
739
|
+
const queuedCount = typeof stats.queuedCount === "number" ? stats.queuedCount : null;
|
|
740
|
+
const processingCount = typeof stats.processingCount === "number" ? stats.processingCount : null;
|
|
741
|
+
const idle = queuedCount !== null &&
|
|
742
|
+
processingCount !== null &&
|
|
743
|
+
queuedCount + processingCount === 0;
|
|
744
|
+
if (passFloorMet && generatedFloorMet && (!requireIdle || idle)) {
|
|
736
745
|
return {
|
|
737
746
|
ready: true,
|
|
738
747
|
attempts,
|
|
739
748
|
elapsedMs: Date.now() - start,
|
|
740
749
|
tableId: schema.tableId,
|
|
741
750
|
pollKey,
|
|
751
|
+
idle,
|
|
742
752
|
floors: {
|
|
743
753
|
minPassedCount,
|
|
744
754
|
minGeneratedMessages,
|
|
@@ -751,6 +761,8 @@ export async function waitForCampaignProcessing(input) {
|
|
|
751
761
|
staleGeneratedMessagesCount: stats.staleGeneratedMessagesCount ?? 0,
|
|
752
762
|
generatedWithoutPassCount: stats.generatedWithoutPassCount ?? 0,
|
|
753
763
|
currentTemplateRevisionHash: currentRevisionHash,
|
|
764
|
+
queuedCount,
|
|
765
|
+
processingCount,
|
|
754
766
|
},
|
|
755
767
|
stats,
|
|
756
768
|
};
|
|
@@ -788,6 +800,11 @@ export async function waitForCampaignProcessing(input) {
|
|
|
788
800
|
generatedFloorMet: minGeneratedMessages === null ||
|
|
789
801
|
(lastStats?.currentRevisionGeneratedMessagesCount ?? 0) >=
|
|
790
802
|
minGeneratedMessages,
|
|
803
|
+
idle: typeof lastStats?.queuedCount === "number" &&
|
|
804
|
+
typeof lastStats?.processingCount === "number" &&
|
|
805
|
+
lastStats.queuedCount + lastStats.processingCount === 0,
|
|
806
|
+
queuedCount: lastStats?.queuedCount ?? null,
|
|
807
|
+
processingCount: lastStats?.processingCount ?? null,
|
|
791
808
|
},
|
|
792
809
|
recovery,
|
|
793
810
|
guidance: "Surface this partial validation checkpoint before taking another action. Use recovery.suggestedToolCalls to retry processing, queue missing work, revise rubrics, record a fresh same-source sample, revise source, or revise message quality instead of moving to Settings on a weak sample.",
|
|
@@ -86,10 +86,10 @@ type IntegrationHomeWorkspacePin = {
|
|
|
86
86
|
};
|
|
87
87
|
/**
|
|
88
88
|
* Mirror the home-workspace consistency invariant owned by
|
|
89
|
-
* `readMcpAgentServiceContext
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
89
|
+
* `readMcpAgentServiceContext`. Customer profiles prove home with the customer
|
|
90
|
+
* workspace lock. Cross-workspace Admin profiles intentionally omit that lock,
|
|
91
|
+
* so their complete signed Agent service context plus the server-authenticated
|
|
92
|
+
* Admin kind proves home instead.
|
|
93
93
|
*
|
|
94
94
|
* The server independently enforces the same boundary. This client pin makes the
|
|
95
95
|
* tool predictable while the active workspace is elsewhere; it is not the
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { readMcpAgentServiceContext } from "../agent-service-auth.js";
|
|
1
2
|
import { getApi, SellableApiError } from "../api.js";
|
|
2
3
|
import { getConfig } from "../auth.js";
|
|
3
4
|
/**
|
|
@@ -93,10 +94,10 @@ const READ_TIMEOUT_MS = 25_000;
|
|
|
93
94
|
const CALL_TIMEOUT_MS = 45_000;
|
|
94
95
|
/**
|
|
95
96
|
* Mirror the home-workspace consistency invariant owned by
|
|
96
|
-
* `readMcpAgentServiceContext
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
97
|
+
* `readMcpAgentServiceContext`. Customer profiles prove home with the customer
|
|
98
|
+
* workspace lock. Cross-workspace Admin profiles intentionally omit that lock,
|
|
99
|
+
* so their complete signed Agent service context plus the server-authenticated
|
|
100
|
+
* Admin kind proves home instead.
|
|
100
101
|
*
|
|
101
102
|
* The server independently enforces the same boundary. This client pin makes the
|
|
102
103
|
* tool predictable while the active workspace is elsewhere; it is not the
|
|
@@ -109,7 +110,27 @@ export function resolveIntegrationHomeWorkspacePin(env = process.env, token = ge
|
|
|
109
110
|
const workspaceId = env.SELLABLE_AGENT_WORKSPACE_ID?.trim();
|
|
110
111
|
const lockWorkspaceId = env.SELLABLE_LOCK_WORKSPACE_ID?.trim();
|
|
111
112
|
const requiresLock = ["1", "true", "yes"].includes((env.SELLABLE_REQUIRE_WORKSPACE_LOCK ?? "").trim().toLowerCase());
|
|
112
|
-
|
|
113
|
+
let serviceContextWorkspaceId = null;
|
|
114
|
+
try {
|
|
115
|
+
serviceContextWorkspaceId =
|
|
116
|
+
readMcpAgentServiceContext(env, token)?.workspaceId ?? null;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
serviceContextWorkspaceId = null;
|
|
120
|
+
}
|
|
121
|
+
const authenticatedKind = (env.SELLABLE_AGENT_SERVER_AUTHENTICATED_KIND ?? "")
|
|
122
|
+
.trim()
|
|
123
|
+
.toUpperCase();
|
|
124
|
+
const verifiedCustomerHome = Boolean(workspaceId) &&
|
|
125
|
+
workspaceId === serviceContextWorkspaceId &&
|
|
126
|
+
workspaceId === lockWorkspaceId &&
|
|
127
|
+
requiresLock;
|
|
128
|
+
const verifiedAdminHome = authenticatedKind === "ADMIN" &&
|
|
129
|
+
Boolean(workspaceId) &&
|
|
130
|
+
workspaceId === serviceContextWorkspaceId &&
|
|
131
|
+
!lockWorkspaceId &&
|
|
132
|
+
!requiresLock;
|
|
133
|
+
if (!verifiedCustomerHome && !verifiedAdminHome) {
|
|
113
134
|
return {
|
|
114
135
|
ok: false,
|
|
115
136
|
envelope: envelope({
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -652,6 +652,7 @@ export declare const allTools: ({
|
|
|
652
652
|
minPassedCount?: undefined;
|
|
653
653
|
minGeneratedMessages?: undefined;
|
|
654
654
|
templateRevision?: undefined;
|
|
655
|
+
requireIdle?: undefined;
|
|
655
656
|
timeoutMs?: undefined;
|
|
656
657
|
intervalMs?: undefined;
|
|
657
658
|
rowIds?: undefined;
|
|
@@ -729,6 +730,7 @@ export declare const allTools: ({
|
|
|
729
730
|
minPassedCount?: undefined;
|
|
730
731
|
minGeneratedMessages?: undefined;
|
|
731
732
|
templateRevision?: undefined;
|
|
733
|
+
requireIdle?: undefined;
|
|
732
734
|
timeoutMs?: undefined;
|
|
733
735
|
intervalMs?: undefined;
|
|
734
736
|
rowIds?: undefined;
|
|
@@ -796,6 +798,7 @@ export declare const allTools: ({
|
|
|
796
798
|
minPassedCount?: undefined;
|
|
797
799
|
minGeneratedMessages?: undefined;
|
|
798
800
|
templateRevision?: undefined;
|
|
801
|
+
requireIdle?: undefined;
|
|
799
802
|
timeoutMs?: undefined;
|
|
800
803
|
intervalMs?: undefined;
|
|
801
804
|
rowIds?: undefined;
|
|
@@ -832,6 +835,9 @@ export declare const allTools: ({
|
|
|
832
835
|
type: string;
|
|
833
836
|
description: string;
|
|
834
837
|
};
|
|
838
|
+
requireIdle: {
|
|
839
|
+
type: string;
|
|
840
|
+
};
|
|
835
841
|
timeoutMs: {
|
|
836
842
|
type: string;
|
|
837
843
|
};
|
|
@@ -889,6 +895,7 @@ export declare const allTools: ({
|
|
|
889
895
|
minPassedCount?: undefined;
|
|
890
896
|
minGeneratedMessages?: undefined;
|
|
891
897
|
templateRevision?: undefined;
|
|
898
|
+
requireIdle?: undefined;
|
|
892
899
|
timeoutMs?: undefined;
|
|
893
900
|
intervalMs?: undefined;
|
|
894
901
|
targetConfig?: undefined;
|
|
@@ -1110,6 +1117,7 @@ export declare const allTools: ({
|
|
|
1110
1117
|
minPassedCount?: undefined;
|
|
1111
1118
|
minGeneratedMessages?: undefined;
|
|
1112
1119
|
templateRevision?: undefined;
|
|
1120
|
+
requireIdle?: undefined;
|
|
1113
1121
|
timeoutMs?: undefined;
|
|
1114
1122
|
intervalMs?: undefined;
|
|
1115
1123
|
rowIds?: undefined;
|
package/package.json
CHANGED
|
@@ -18,6 +18,7 @@ allowed-tools:
|
|
|
18
18
|
- mcp__sellable__search_subskill_prompts
|
|
19
19
|
- mcp__sellable__list_senders
|
|
20
20
|
- mcp__sellable__select_campaign_cells
|
|
21
|
+
- mcp__sellable__wait_for_campaign_processing
|
|
21
22
|
---
|
|
22
23
|
|
|
23
24
|
# Refill Sends
|
|
@@ -591,8 +592,16 @@ asset is the contract to load — load the prompt and that asset, verify the `v3
|
|
|
591
592
|
compatible range, and report the version before the first call. Call
|
|
592
593
|
`refill_v3_advance` with `{workspaceId, scope}` — plus `yolo: true` only when the
|
|
593
594
|
operator asked for `--yolo` — and call it again after each `advanced` or
|
|
594
|
-
`campaign_attention_required` result
|
|
595
|
-
`
|
|
595
|
+
`campaign_attention_required` result. An `awaiting_external_change` result with
|
|
596
|
+
`deferral.code:"campaign_work_in_flight"` and a campaign id is a bounded
|
|
597
|
+
read-only continuation, not permission to walk the next campaign: call
|
|
598
|
+
`wait_for_campaign_processing({ workspaceId, campaignId, requireIdle:true })`,
|
|
599
|
+
then call `refill_v3_advance` again with the identical scope and yolo grant.
|
|
600
|
+
This reuses Create Campaign's campaign-table waiter and guarantees the same
|
|
601
|
+
campaign is freshly replanned after its cohort settles. If the bounded wait
|
|
602
|
+
returns a partial timeout, surface that checkpoint and make the fresh advance;
|
|
603
|
+
if it reports the same live campaign, repeat the bounded wait. Stop on every
|
|
604
|
+
other `awaiting_external_change`, `complete`, or `blocked` result.
|
|
596
605
|
|
|
597
606
|
Resolve the workspace BEFORE the first call, exactly as the V1 route already
|
|
598
607
|
requires. `workspaceId` must be an exact id on every automation call: when the
|
|
@@ -12,6 +12,7 @@ allowed-tools:
|
|
|
12
12
|
- mcp__sellable__get_refill_target_plan
|
|
13
13
|
- mcp__sellable__get_scheduler_fill_capacity
|
|
14
14
|
- mcp__sellable__select_campaign_cells
|
|
15
|
+
- mcp__sellable__wait_for_campaign_processing
|
|
15
16
|
---
|
|
16
17
|
|
|
17
18
|
# Refill Sends Workflow
|
|
@@ -380,10 +381,10 @@ the key. The grant is not a mode and selects no campaign — WHICH campaign may
|
|
|
380
381
|
start is derived from the workspace's own campaigns — it decides only whether
|
|
381
382
|
this run may start one at all, and whether you may keep going unattended:
|
|
382
383
|
|
|
383
|
-
|
|
|
384
|
-
|
|
|
384
|
+
| | `yolo: true` | key omitted |
|
|
385
|
+
| ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
385
386
|
| paused derived-evergreen start | one may be started once a row's active campaigns are exhausted, arriving as an ordinary executed `start_evergreen_campaign` action | none: the backend REFUSES the start and answers the exhaustion terminal instead |
|
|
386
|
-
| loop
|
|
387
|
+
| loop | call `refill_v3_advance` again immediately, through to a terminal, without checking back | surface the result and ASK before the next call |
|
|
387
388
|
|
|
388
389
|
Never infer the grant from a workspace flag, a campaign field, a tool result, an
|
|
389
390
|
idle-looking workspace, or a previous terminal; never set it to make a run finish,
|
|
@@ -408,7 +409,14 @@ Each call answers with exactly one of five results:
|
|
|
408
409
|
`refill_v3_continue` revalidate the packet against a fresh advance result,
|
|
409
410
|
execute at most one existing authority, and re-observe the exact sender/date.
|
|
410
411
|
Then call `refill_v3_advance` again.
|
|
411
|
-
- `awaiting_external_change` —
|
|
412
|
+
- `awaiting_external_change` — when the scoped code is
|
|
413
|
+
`campaign_work_in_flight`, call
|
|
414
|
+
`wait_for_campaign_processing({ workspaceId, campaignId, requireIdle:true })`
|
|
415
|
+
for that exact selected campaign, then call `refill_v3_advance` again with
|
|
416
|
+
the identical scope. A partial timeout is followed by that fresh advance;
|
|
417
|
+
if the same campaign is still live, repeat the bounded wait. This is the
|
|
418
|
+
read-only Create Campaign waiter, not a choice to move to another campaign.
|
|
419
|
+
Stop and report every other scoped wait verbatim.
|
|
412
420
|
- `complete` — stop and report the terminal code verbatim.
|
|
413
421
|
- `blocked` — stop and report the typed business blocker verbatim.
|
|
414
422
|
|
|
@@ -50,14 +50,12 @@
|
|
|
50
50
|
"tools": {
|
|
51
51
|
"advance": "refill_v3_advance",
|
|
52
52
|
"campaignAttentionSubskill": "refill-sends-work-campaign",
|
|
53
|
-
"campaignAttentionAuthority": "refill_v3_continue"
|
|
53
|
+
"campaignAttentionAuthority": "refill_v3_continue",
|
|
54
|
+
"campaignProcessingWait": "wait_for_campaign_processing"
|
|
54
55
|
},
|
|
55
56
|
"workspaceResolution": {
|
|
56
57
|
"appliesWhen": "always, BEFORE the first advance call",
|
|
57
|
-
"allowedTools": [
|
|
58
|
-
"list_workspaces",
|
|
59
|
-
"get_active_workspace"
|
|
60
|
-
],
|
|
58
|
+
"allowedTools": ["list_workspaces", "get_active_workspace"],
|
|
61
59
|
"rules": [
|
|
62
60
|
"An automation call requires an exact explicit workspaceId. Never pass a workspace NAME to refill_v3_advance and never let it fall back to the configured workspace when the operator named one.",
|
|
63
61
|
"When the operator names a workspace, call list_workspaces FIRST and match that name to an exact workspaceId; pass that id on every advance call for the rest of the run.",
|
|
@@ -98,26 +96,16 @@
|
|
|
98
96
|
"loop": {
|
|
99
97
|
"call": {
|
|
100
98
|
"tool": "refill_v3_advance",
|
|
101
|
-
"inputKeys": [
|
|
102
|
-
"workspaceId",
|
|
103
|
-
"scope",
|
|
104
|
-
"yolo"
|
|
105
|
-
],
|
|
99
|
+
"inputKeys": ["workspaceId", "scope", "yolo"],
|
|
106
100
|
"note": "Pass workspaceId and scope with the values the host resolved once, plus yolo:true only when the autonomy step granted it. workspaceId is the EXACT id workspaceResolution produced, never a name and never an implicit config default when the operator named a workspace. There is no mode, continuation, task receipt, retry counter, cursor, row, action, or receipt-fact input, and a call that supplies one is refused by the backend parser before any observation.",
|
|
107
|
-
"requiredInputKeys": [
|
|
108
|
-
"workspaceId",
|
|
109
|
-
"scope"
|
|
110
|
-
]
|
|
101
|
+
"requiredInputKeys": ["workspaceId", "scope"]
|
|
111
102
|
},
|
|
112
103
|
"repeatWhile": [
|
|
113
104
|
"advanced",
|
|
114
|
-
"campaign_attention_required"
|
|
115
|
-
|
|
116
|
-
"stopOn": [
|
|
117
|
-
"awaiting_external_change",
|
|
118
|
-
"complete",
|
|
119
|
-
"blocked"
|
|
105
|
+
"campaign_attention_required",
|
|
106
|
+
"awaiting_external_change:campaign_work_in_flight_after_wait"
|
|
120
107
|
],
|
|
108
|
+
"stopOn": ["awaiting_external_change:other", "complete", "blocked"],
|
|
121
109
|
"note": "Call advance again with the SAME two keys. Losing a prior result is harmless: every invocation reconstructs from fresh world state plus server-loaded authority receipts.",
|
|
122
110
|
"repeatPolicy": {
|
|
123
111
|
"granted": "Call advance again immediately, without checking back.",
|
|
@@ -143,18 +131,9 @@
|
|
|
143
131
|
"alreadyExecuted": false,
|
|
144
132
|
"route": {
|
|
145
133
|
"subskill": "refill-sends-work-campaign",
|
|
146
|
-
"pass": [
|
|
147
|
-
"packet.scope",
|
|
148
|
-
"packet.evidence"
|
|
149
|
-
],
|
|
134
|
+
"pass": ["packet.scope", "packet.evidence"],
|
|
150
135
|
"returnThrough": "refill_v3_continue",
|
|
151
|
-
"returnInput": [
|
|
152
|
-
"workspaceId",
|
|
153
|
-
"scope",
|
|
154
|
-
"packet",
|
|
155
|
-
"decision",
|
|
156
|
-
"yolo"
|
|
157
|
-
]
|
|
136
|
+
"returnInput": ["workspaceId", "scope", "packet", "decision", "yolo"]
|
|
158
137
|
},
|
|
159
138
|
"then": "call the advance tool again",
|
|
160
139
|
"note": "This is the ONE model judgment in the flow. The backend already selected exactly one campaign and bounded the evidence; the subskill chooses one action from its own closed vocabulary and its deterministic authority validates, executes, and re-observes it."
|
|
@@ -168,14 +147,24 @@
|
|
|
168
147
|
"deferral.code",
|
|
169
148
|
"deferral.resumeAt"
|
|
170
149
|
],
|
|
171
|
-
"
|
|
150
|
+
"campaignWorkInFlight": {
|
|
151
|
+
"appliesToDeferralCode": "campaign_work_in_flight",
|
|
152
|
+
"wait": {
|
|
153
|
+
"tool": "wait_for_campaign_processing",
|
|
154
|
+
"input": {
|
|
155
|
+
"campaignId": "deferral.campaignId",
|
|
156
|
+
"workspaceId": "workspaceId",
|
|
157
|
+
"requireIdle": true
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"then": "call the advance tool again with the identical workspaceId, scope, and yolo grant",
|
|
161
|
+
"note": "This is a bounded read-only wait inherited from Create Campaign. It holds the same campaign while its cells settle; it never authorizes selecting a sibling. A partial timeout returns to fresh advance, and the same deferral may authorize another bounded wait."
|
|
162
|
+
},
|
|
163
|
+
"then": "for any other deferral code, stop and report the scoped wait verbatim"
|
|
172
164
|
},
|
|
173
165
|
"complete": {
|
|
174
166
|
"alreadyExecuted": false,
|
|
175
|
-
"surface": [
|
|
176
|
-
"terminal",
|
|
177
|
-
"observation"
|
|
178
|
-
],
|
|
167
|
+
"surface": ["terminal", "observation"],
|
|
179
168
|
"then": "stop and report the terminal code verbatim"
|
|
180
169
|
},
|
|
181
170
|
"blocked": {
|
|
@@ -204,6 +193,6 @@
|
|
|
204
193
|
"Every advance call carried exactly workspaceId and scope.",
|
|
205
194
|
"Every already-executed result was surfaced, never re-executed.",
|
|
206
195
|
"Only campaign_attention_required loaded the campaign subskill.",
|
|
207
|
-
"
|
|
196
|
+
"campaign_work_in_flight used the bounded campaign table waiter and returned to a fresh advance before any sibling campaign; every other awaiting_external_change, complete, or blocked result stopped the run."
|
|
208
197
|
]
|
|
209
198
|
}
|