@sellable/mcp 0.1.513 → 0.1.514
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/refill-journal.d.ts +26 -0
- package/dist/refill-journal.js +69 -1
- package/dist/refill-local-state.d.ts +21 -0
- package/dist/refill-local-state.js +177 -1
- package/dist/refill-run-client.d.ts +62 -0
- package/dist/refill-run-client.js +101 -0
- package/dist/refill-run-loop.d.ts +100 -0
- package/dist/refill-run-loop.js +1238 -0
- package/dist/server.js +1 -1
- package/dist/tools/campaign-processing.js +3 -3
- package/dist/tools/evergreen-refill-plan.d.ts +6 -0
- package/dist/tools/evergreen-refill-plan.js +1 -1
- package/dist/tools/refill-executors.d.ts +178 -0
- package/dist/tools/refill-executors.js +788 -0
- package/dist/tools/refill-sends-v2.d.ts +94 -7
- package/dist/tools/refill-sends-v2.js +143 -30
- package/dist/tools/refill-sends.js +2 -657
- package/dist/tools/registry.d.ts +168 -0
- package/package.json +1 -1
- package/skills/refill-sends-v2/SKILL.md +113 -53
- package/skills/refill-sends-v2-workflow/SKILL.md +112 -101
- package/skills/refill-sends-v2-workflow/core/flow.v1.json +137 -31
package/dist/tools/registry.d.ts
CHANGED
|
@@ -474,6 +474,39 @@ export declare const allTools: ({
|
|
|
474
474
|
required: string[];
|
|
475
475
|
additionalProperties: boolean;
|
|
476
476
|
};
|
|
477
|
+
} | {
|
|
478
|
+
name: string;
|
|
479
|
+
description: string;
|
|
480
|
+
inputSchema: {
|
|
481
|
+
type: string;
|
|
482
|
+
properties: {
|
|
483
|
+
intent: {
|
|
484
|
+
type: string;
|
|
485
|
+
enum: string[];
|
|
486
|
+
description: string;
|
|
487
|
+
};
|
|
488
|
+
campaignId: {
|
|
489
|
+
type: string;
|
|
490
|
+
description: string;
|
|
491
|
+
};
|
|
492
|
+
tableId: {
|
|
493
|
+
type: string;
|
|
494
|
+
description: string;
|
|
495
|
+
};
|
|
496
|
+
limit: {
|
|
497
|
+
type: string;
|
|
498
|
+
minimum: number;
|
|
499
|
+
maximum: number;
|
|
500
|
+
description: string;
|
|
501
|
+
};
|
|
502
|
+
workspaceId: {
|
|
503
|
+
type: string;
|
|
504
|
+
description: string;
|
|
505
|
+
};
|
|
506
|
+
};
|
|
507
|
+
required: string[];
|
|
508
|
+
additionalProperties: boolean;
|
|
509
|
+
};
|
|
477
510
|
} | {
|
|
478
511
|
name: string;
|
|
479
512
|
description: string;
|
|
@@ -2295,6 +2328,24 @@ export declare const allTools: ({
|
|
|
2295
2328
|
};
|
|
2296
2329
|
required: string[];
|
|
2297
2330
|
};
|
|
2331
|
+
} | {
|
|
2332
|
+
name: string;
|
|
2333
|
+
description: string;
|
|
2334
|
+
inputSchema: {
|
|
2335
|
+
type: string;
|
|
2336
|
+
properties: {
|
|
2337
|
+
senderId: {
|
|
2338
|
+
type: string;
|
|
2339
|
+
description: string;
|
|
2340
|
+
};
|
|
2341
|
+
workspaceId: {
|
|
2342
|
+
type: string;
|
|
2343
|
+
description: string;
|
|
2344
|
+
};
|
|
2345
|
+
};
|
|
2346
|
+
required: string[];
|
|
2347
|
+
additionalProperties: boolean;
|
|
2348
|
+
};
|
|
2298
2349
|
} | {
|
|
2299
2350
|
name: string;
|
|
2300
2351
|
description: string;
|
|
@@ -2583,6 +2634,43 @@ export declare const allTools: ({
|
|
|
2583
2634
|
};
|
|
2584
2635
|
required: never[];
|
|
2585
2636
|
};
|
|
2637
|
+
} | {
|
|
2638
|
+
name: string;
|
|
2639
|
+
description: string;
|
|
2640
|
+
inputSchema: {
|
|
2641
|
+
type: string;
|
|
2642
|
+
properties: {
|
|
2643
|
+
workspaceId: {
|
|
2644
|
+
type: string;
|
|
2645
|
+
description: string;
|
|
2646
|
+
};
|
|
2647
|
+
senderIds: {
|
|
2648
|
+
type: string;
|
|
2649
|
+
items: {
|
|
2650
|
+
type: string;
|
|
2651
|
+
};
|
|
2652
|
+
};
|
|
2653
|
+
runState: {
|
|
2654
|
+
type: string;
|
|
2655
|
+
description: string;
|
|
2656
|
+
};
|
|
2657
|
+
intent: {
|
|
2658
|
+
type: string;
|
|
2659
|
+
enum: string[];
|
|
2660
|
+
description: string;
|
|
2661
|
+
};
|
|
2662
|
+
journal: {
|
|
2663
|
+
type: string;
|
|
2664
|
+
description: string;
|
|
2665
|
+
};
|
|
2666
|
+
journalNote: {
|
|
2667
|
+
type: string;
|
|
2668
|
+
description: string;
|
|
2669
|
+
};
|
|
2670
|
+
};
|
|
2671
|
+
required: string[];
|
|
2672
|
+
additionalProperties: boolean;
|
|
2673
|
+
};
|
|
2586
2674
|
} | {
|
|
2587
2675
|
name: string;
|
|
2588
2676
|
description: string;
|
|
@@ -7193,6 +7281,33 @@ export declare const allTools: ({
|
|
|
7193
7281
|
type: string;
|
|
7194
7282
|
description: string;
|
|
7195
7283
|
};
|
|
7284
|
+
runId: {
|
|
7285
|
+
type: string;
|
|
7286
|
+
description: string;
|
|
7287
|
+
};
|
|
7288
|
+
fence: {
|
|
7289
|
+
type: string;
|
|
7290
|
+
description: string;
|
|
7291
|
+
};
|
|
7292
|
+
dryRun: {
|
|
7293
|
+
type: string;
|
|
7294
|
+
description: string;
|
|
7295
|
+
};
|
|
7296
|
+
approvalMode: {
|
|
7297
|
+
type: string;
|
|
7298
|
+
enum: string[];
|
|
7299
|
+
description: string;
|
|
7300
|
+
};
|
|
7301
|
+
senderIds: {
|
|
7302
|
+
type: string;
|
|
7303
|
+
items: {
|
|
7304
|
+
type: string;
|
|
7305
|
+
};
|
|
7306
|
+
};
|
|
7307
|
+
intent: {
|
|
7308
|
+
type: string;
|
|
7309
|
+
enum: string[];
|
|
7310
|
+
};
|
|
7196
7311
|
};
|
|
7197
7312
|
required: string[];
|
|
7198
7313
|
additionalProperties: boolean;
|
|
@@ -7541,6 +7656,59 @@ export declare const allTools: ({
|
|
|
7541
7656
|
required: string[];
|
|
7542
7657
|
additionalProperties: boolean;
|
|
7543
7658
|
};
|
|
7659
|
+
} | {
|
|
7660
|
+
name: string;
|
|
7661
|
+
description: string;
|
|
7662
|
+
inputSchema: {
|
|
7663
|
+
type: string;
|
|
7664
|
+
properties: {
|
|
7665
|
+
capacityRequests: {
|
|
7666
|
+
type: string;
|
|
7667
|
+
minItems: number;
|
|
7668
|
+
items: {
|
|
7669
|
+
type: string;
|
|
7670
|
+
properties: {
|
|
7671
|
+
senderId: {
|
|
7672
|
+
type: string;
|
|
7673
|
+
description: string;
|
|
7674
|
+
};
|
|
7675
|
+
actionType: {
|
|
7676
|
+
type: string;
|
|
7677
|
+
enum: string[];
|
|
7678
|
+
description: string;
|
|
7679
|
+
};
|
|
7680
|
+
cellId: {
|
|
7681
|
+
type: string;
|
|
7682
|
+
description: string;
|
|
7683
|
+
};
|
|
7684
|
+
columnId: {
|
|
7685
|
+
type: string;
|
|
7686
|
+
description: string;
|
|
7687
|
+
};
|
|
7688
|
+
};
|
|
7689
|
+
required: string[];
|
|
7690
|
+
additionalProperties: boolean;
|
|
7691
|
+
};
|
|
7692
|
+
description: string;
|
|
7693
|
+
};
|
|
7694
|
+
targetDate: {
|
|
7695
|
+
type: string;
|
|
7696
|
+
pattern: string;
|
|
7697
|
+
description: string;
|
|
7698
|
+
};
|
|
7699
|
+
mode: {
|
|
7700
|
+
type: string;
|
|
7701
|
+
enum: string[];
|
|
7702
|
+
description: string;
|
|
7703
|
+
};
|
|
7704
|
+
workspaceId: {
|
|
7705
|
+
type: string;
|
|
7706
|
+
description: string;
|
|
7707
|
+
};
|
|
7708
|
+
};
|
|
7709
|
+
required: string[];
|
|
7710
|
+
additionalProperties: boolean;
|
|
7711
|
+
};
|
|
7544
7712
|
} | {
|
|
7545
7713
|
name: string;
|
|
7546
7714
|
description: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: refill-sends-v2
|
|
3
|
-
description:
|
|
3
|
+
description: Execute refill sends v2 through the fenced evergreen refill loop, with dry-run and resume support.
|
|
4
4
|
visibility: public
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- mcp__sellable__refill_sends_v2
|
|
@@ -15,19 +15,20 @@ allowed-tools:
|
|
|
15
15
|
|
|
16
16
|
# Refill Sends V2
|
|
17
17
|
|
|
18
|
-
Use this
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
Use this command for refill requests such as "refill sends", "fill evergreen
|
|
19
|
+
senders", "load everyone up", "run Damiano", or "show a dry run for this
|
|
20
|
+
workspace".
|
|
21
21
|
|
|
22
22
|
Host command names:
|
|
23
23
|
|
|
24
24
|
- Claude Code: `/sellable:refill-sends-v2`
|
|
25
25
|
- Codex: `$sellable:refill-sends-v2`
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
`refill_sends_v2` is the execution surface. In real-run mode it starts or
|
|
28
|
+
resumes a fenced refill run, reads a fresh packet, executes only the packet's
|
|
29
|
+
named bounded work, verifies the result, and returns either a terminal report, a
|
|
30
|
+
blocked report, or an in-progress resume handle. In dry-run mode it stays
|
|
31
|
+
read-only and writes only a dry-run journal.
|
|
31
32
|
|
|
32
33
|
## Entry
|
|
33
34
|
|
|
@@ -36,61 +37,120 @@ active workspace readback. Scheduled or autonomous usage must carry
|
|
|
36
37
|
`workspaceId` on every tool call. If the workspace is missing or ambiguous, stop
|
|
37
38
|
with `WORKSPACE_REQUIRED`; do not switch the shared active workspace.
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
For a real refill run:
|
|
40
41
|
|
|
41
42
|
```text
|
|
42
|
-
refill_sends_v2({ workspaceId })
|
|
43
|
+
refill_sends_v2({ workspaceId, intent:"auto", senderIds?, approvalMode? })
|
|
43
44
|
```
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
For read-only inspection:
|
|
46
47
|
|
|
47
48
|
```text
|
|
48
|
-
|
|
49
|
-
get_subskill_asset({ subskillName: "refill-sends-v2-workflow", assetPath: "core/flow.v1.json" })
|
|
49
|
+
refill_sends_v2({ workspaceId, dryRun:true, intent:"auto", senderIds? })
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
`workflow:"refill-sends-v2-workflow"` with a `v1` version before the planner
|
|
54
|
-
call.
|
|
52
|
+
To resume an in-progress run, pass the handle back exactly:
|
|
55
53
|
|
|
56
|
-
|
|
54
|
+
```text
|
|
55
|
+
refill_sends_v2({ workspaceId, runId, fence })
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
If a stale handle loses the lease, the tool reports the holder status and the
|
|
59
|
+
approximately 10 minute lockout window. Reinvoke with the current handle or wait
|
|
60
|
+
for lease expiry; never guess a fence.
|
|
61
|
+
|
|
62
|
+
The default `intent:"auto"` inspects `managed_waterfall`,
|
|
63
|
+
`dashboard_evergreen`, and `active_campaign` lane sources. Report the lane
|
|
64
|
+
source and lane chain as proof for every selected sender.
|
|
65
|
+
|
|
66
|
+
If membership blocks a workspace read, report the structured
|
|
67
|
+
`workspace_access` blocker instead of retrying auth or switching workspaces.
|
|
68
|
+
|
|
69
|
+
## Authority
|
|
70
|
+
|
|
71
|
+
The run may execute only packet-named bounded work:
|
|
72
|
+
|
|
73
|
+
- approve generated messages that are ready for review (`approve_messages`);
|
|
74
|
+
- enrich the next batch of unenriched rows (`enrich_more`);
|
|
75
|
+
- copy leads already found into the campaign table (`reconcile_source_copy`);
|
|
76
|
+
- re-run errored enrichment/message cells (`rerun_errored_cells`);
|
|
77
|
+
- find more leads via this campaign's original source (`add_leads_same_source`)
|
|
78
|
+
only for mechanical same-source continuations;
|
|
79
|
+
- start the paused campaign so ready rows can schedule (`start_campaign`) only
|
|
80
|
+
when the campaign is in the packet's pinned lane chain;
|
|
81
|
+
- refresh paid InMail credit facts during bootstrap and once per scheduler-wait
|
|
82
|
+
entry when the packet requires it.
|
|
83
|
+
|
|
84
|
+
The loop records planned -> did -> outcome before and after every foreign
|
|
85
|
+
mutation. It refuses stale packets by fingerprint and validates packet
|
|
86
|
+
coherence before dispatch. The planner owns repair decisions: if a batch needs
|
|
87
|
+
repair, the next packet names the repair rung; the loop bounds and refuses, it
|
|
88
|
+
does not improvise fixes.
|
|
89
|
+
|
|
90
|
+
Do not create campaigns, switch provider families, lower thresholds, write
|
|
91
|
+
scheduler fields, send messages, archive/delete campaigns, or mutate
|
|
92
|
+
brief/filter/message/sequence/sender config unless a separate exact approval
|
|
93
|
+
packet explicitly authorizes that work. In short: no campaign creation, no
|
|
94
|
+
provider-family switch, no threshold lowering, no scheduler writes, no
|
|
95
|
+
launch/send/archive/delete, and no brief/filter/message/sequence/sender
|
|
96
|
+
mutation.
|
|
97
|
+
|
|
98
|
+
## Continuations
|
|
99
|
+
|
|
100
|
+
Sales Nav and Prospeo source continuations that are not yolo-safe are blocked
|
|
101
|
+
as executable scoped handoffs. The report will include text shaped like:
|
|
57
102
|
|
|
58
103
|
```text
|
|
59
|
-
|
|
104
|
+
$sellable:create-campaign [campaignId]
|
|
60
105
|
```
|
|
61
106
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- `
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
107
|
+
That handoff is run in a separate thread only after explicit approval. Scope is
|
|
108
|
+
strict: add leads through this campaign's existing source, keep the same
|
|
109
|
+
saved-search identity, import mode `add` into the same source list, and do
|
|
110
|
+
source work only. It is never a new campaign, provider-family switch, brief
|
|
111
|
+
change, rubric change, message change, sequence change, or sender change.
|
|
112
|
+
|
|
113
|
+
## Verification
|
|
114
|
+
|
|
115
|
+
The loop verifies whole rows before replanning. It reattaches to an own active
|
|
116
|
+
prep job instead of re-dispatching, waits on foreign prep jobs without adopting
|
|
117
|
+
their outcomes, waits on active enrichment/import work by rereading the packet,
|
|
118
|
+
and treats capped scheduler capacity as complete.
|
|
119
|
+
|
|
120
|
+
Scheduler waits are cross-invocation. Each tool call polls briefly under the
|
|
121
|
+
host guard, heartbeats the run lease, and may return:
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
{ status:"in_progress", runId, fence, gate, guidance }
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Reinvoke with that handle. The approximately five minute scheduler budget is at
|
|
128
|
+
the run level, not one tool call. A window-closed or loaded-awaiting scheduler
|
|
129
|
+
report must include remaining-ready count, exact expected pickup time, and the
|
|
130
|
+
resume handle; never treat bare "awaiting scheduler" copy as a final answer.
|
|
131
|
+
|
|
132
|
+
After the first prep batch, read the conversion-verdict journal line. It is
|
|
133
|
+
rendered from packet facts: `supplyCensus`, `censusReason`, and
|
|
134
|
+
`pipelineDiagnosis.firstFailing`. If the verdict is honest rubric failure, the
|
|
135
|
+
human decision is to update the rubric or change lead source; refill does not
|
|
136
|
+
mutate those automatically.
|
|
137
|
+
|
|
138
|
+
## Results
|
|
139
|
+
|
|
140
|
+
Terminal reasons are:
|
|
141
|
+
|
|
142
|
+
- `complete`
|
|
143
|
+
- `capped_by_scheduler`
|
|
144
|
+
- `loaded_awaiting_scheduler`
|
|
145
|
+
- `lanes_exhausted`
|
|
146
|
+
- `blocked`
|
|
147
|
+
- `no_refillable_campaigns`
|
|
148
|
+
- `not_an_evergreen_workspace`
|
|
149
|
+
|
|
150
|
+
Report campaign names and sender names first, ids second. Include the terminal
|
|
151
|
+
reason or resume handle, lane source, lane chain, chosen label with token
|
|
152
|
+
secondary, plan revision, journal path, blocked continuation packets, and
|
|
153
|
+
firstFailing checklist when present.
|
|
154
|
+
|
|
155
|
+
Real-run journals live under `~/.sellable/refill/runs` by default and append an
|
|
156
|
+
index line. Dry runs include the dry marker and do not create run records.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: refill-sends-v2-workflow
|
|
3
|
-
description: Internal
|
|
3
|
+
description: Internal execution workflow for refill sends v2 fenced runs.
|
|
4
4
|
visibility: internal
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- mcp__sellable__refill_sends_v2
|
|
@@ -15,113 +15,124 @@ allowed-tools:
|
|
|
15
15
|
|
|
16
16
|
# Refill Sends V2 Workflow
|
|
17
17
|
|
|
18
|
-
This internal workflow
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
and
|
|
18
|
+
This internal workflow mirrors the run-record gates enforced by
|
|
19
|
+
`refill_sends_v2`: bootstrap, plan, execute, verify, and report. Dry runs stay
|
|
20
|
+
read-only. Real runs execute only packet-named bounded work under a fenced run
|
|
21
|
+
lease and return terminal, blocked, or in-progress results.
|
|
22
22
|
|
|
23
23
|
Runtime flow asset: after loading this prompt, load
|
|
24
24
|
`get_subskill_asset({ subskillName: "refill-sends-v2-workflow", assetPath: "core/flow.v1.json" })`
|
|
25
25
|
through MCP, continue chunks until `hasMore:false`, parse the JSON, and verify
|
|
26
|
-
`workflow:"refill-sends-v2-workflow"` with a `v1` version before
|
|
27
|
-
|
|
26
|
+
`workflow:"refill-sends-v2-workflow"` with a `v1` version before driving the
|
|
27
|
+
loop. If the asset cannot load or parse, stop with
|
|
28
28
|
`blocked:refill_sends_v2_workflow_asset_unavailable`; do not emulate it from
|
|
29
29
|
local files or memory.
|
|
30
30
|
|
|
31
|
-
## G0 Bootstrap
|
|
31
|
+
## G0 Bootstrap
|
|
32
32
|
|
|
33
|
-
Resolve
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
Resolve request-scoped `workspaceId` using read-only auth and workspace tools.
|
|
34
|
+
Scheduled or autonomous runs must not rely on implicit workspace state.
|
|
35
|
+
|
|
36
|
+
Start or resume the execution loop:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
refill_sends_v2({ workspaceId, intent:"auto", senderIds?, approvalMode?, runId?, fence? })
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Use `dryRun:true` only when the user asked for read-only inspection. A dry run
|
|
43
|
+
writes a journal only. A real run creates or resumes a run record, refreshes
|
|
44
|
+
paid-credit trust only when packet facts require it, and returns a resume handle
|
|
45
|
+
when the current invocation must pause.
|
|
46
|
+
|
|
47
|
+
## G1 Plan
|
|
48
|
+
|
|
49
|
+
The loop reads `get_refill_plan_v2` with runState fed back from the run record.
|
|
50
|
+
It captures `planRevision`, `stateRevision`, and `targetShapeRevision`, then
|
|
51
|
+
validates the packet before dispatch. Packet coherence is required: fingerprint
|
|
52
|
+
shape, tool input completeness, lane-chain membership, census-vs-rung
|
|
53
|
+
consistency, and terminal/action exclusivity. An incoherent packet is replanned
|
|
54
|
+
once, then blocked as `packet_incoherent`.
|
|
55
|
+
|
|
56
|
+
The packet's `supplyCensus`, `censusReason`, and `pipelineDiagnosis` checklist
|
|
57
|
+
are the reason for the next rung. Repair is replan-driven: the planner names
|
|
58
|
+
the repair rung, such as re-run errored enrichment/message cells
|
|
59
|
+
(`rerun_errored_cells`), approve generated messages that are ready for review
|
|
60
|
+
(`approve_messages`), or start the paused campaign so ready rows can schedule
|
|
61
|
+
(`start_campaign`). The loop bounds and refuses repair loops; it never invents
|
|
62
|
+
a fix list.
|
|
63
|
+
|
|
64
|
+
Use plain-language labels first and tokens second, for example "copy leads
|
|
65
|
+
already found into the campaign table (`reconcile_source_copy`)".
|
|
66
|
+
|
|
67
|
+
## G2 Execute
|
|
68
|
+
|
|
69
|
+
The loop executes only the packet head action whose fingerprint was captured at
|
|
70
|
+
G1. Stale packets are refused and replanned.
|
|
71
|
+
|
|
72
|
+
Allowed packet-named work:
|
|
73
|
+
|
|
74
|
+
1. start the paused campaign so ready rows can schedule (`start_campaign`) when
|
|
75
|
+
the campaign is in the pinned lane chain;
|
|
76
|
+
2. approve generated messages that are ready for review (`approve_messages`);
|
|
77
|
+
3. enrich the next batch of unenriched rows (`enrich_more`);
|
|
78
|
+
4. copy leads already found into the campaign table (`reconcile_source_copy`);
|
|
79
|
+
5. re-run errored enrichment/message cells (`rerun_errored_cells`);
|
|
80
|
+
6. find more leads via this campaign's original source
|
|
81
|
+
(`add_leads_same_source`) for mechanical same-source continuations;
|
|
82
|
+
7. wait for the scheduler to pick up ready rows (`wait_for_scheduler`).
|
|
83
|
+
|
|
84
|
+
Never create campaigns, switch providers, lower thresholds, write scheduler
|
|
85
|
+
fields, send/archive/delete, or mutate brief/filter/message/sequence/sender
|
|
86
|
+
config inside refill.
|
|
87
|
+
|
|
88
|
+
Sales Nav and Prospeo continuations that need human source work are blocked as
|
|
89
|
+
scoped handoffs:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
$sellable:create-campaign [campaignId]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The handoff scope is source work only: same saved-search identity, import mode
|
|
96
|
+
`add` into the same source list, no new campaign, no provider-family switch, and
|
|
97
|
+
no brief/rubric/message/sequence/sender changes without a separate approval
|
|
37
98
|
packet.
|
|
38
99
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
`
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
waterfall can fall back to an existing supported lane.
|
|
79
|
-
8. `next_campaign`: the current lane is exhausted, cooling down, pinned away, or
|
|
80
|
-
unsafe, and the next surviving campaign lane should be inspected.
|
|
81
|
-
9. `wait_for_scheduler`: ready or projected supply covers the target, and only
|
|
82
|
-
scheduler pickup remains.
|
|
83
|
-
10. `done`: the sender or lane is complete for the selected target window, a
|
|
84
|
-
scheduler cap makes additional preparation unnecessary, or
|
|
85
|
-
`no_refillable_campaigns` is the honest terminal.
|
|
86
|
-
|
|
87
|
-
Forward-only lane rule: a lane can move to a later rung or a later surviving
|
|
88
|
-
campaign, but the dry-run packet must not jump backward to invent work that the
|
|
89
|
-
facts do not support. Pinned-campaign rule: a pinned campaign stays selected
|
|
90
|
-
until the planner proves a blocker, cooldown, exhaustion, or safer next lane.
|
|
91
|
-
Capped-is-complete rule: when scheduler capacity is lower than the requested
|
|
92
|
-
target and ready/projected coverage satisfies that cap, report `done` with the
|
|
93
|
-
cap reason. Honest-itinerary rule: show what was checked, what was skipped, and
|
|
94
|
-
why; never hide uncertainty behind a confident source recommendation.
|
|
95
|
-
|
|
96
|
-
Guardrails: no campaign creation, no provider-family switch, no threshold
|
|
97
|
-
lowering, no scheduler writes, no launch/send/archive/delete, no
|
|
98
|
-
brief/filter/message/sequence/sender mutation, no message preparation, no
|
|
99
|
-
message approval, no paid InMail credit refresh, no source mutation, no row
|
|
100
|
-
queueing, and no campaign status change.
|
|
101
|
-
|
|
102
|
-
## Journal
|
|
103
|
-
|
|
104
|
-
`get_refill_plan_v2` writes a local dry-run journal unless `journal:false` is
|
|
105
|
-
passed. Read the returned `journalPath` from the tool result and include it in
|
|
106
|
-
the report. The journal contains bootstrap, plan, and terminal sections plus an
|
|
107
|
-
index line under the run journal directory. If the tool returns
|
|
108
|
-
`journalPath:null` with a `journalWriteFailed` warning, report the warning and
|
|
109
|
-
continue with the dry-run packet; do not retry by writing local files yourself.
|
|
110
|
-
|
|
111
|
-
## Report Contract
|
|
112
|
-
|
|
113
|
-
Completion means packet reviewed and journal written. Merely calling
|
|
114
|
-
`get_refill_plan_v2` is not completion proof.
|
|
115
|
-
|
|
116
|
-
Report these facts:
|
|
117
|
-
|
|
118
|
-
- workspace id and selected sender scope;
|
|
119
|
-
- plan revision and state revision;
|
|
120
|
-
- selected campaign, lane source, and laneChain per sender;
|
|
121
|
-
- chosen rung and dry-run action queue;
|
|
122
|
-
- itinerary, skipped lanes, blockers, cooldowns, and warnings;
|
|
123
|
-
- `no_refillable_campaigns` terminals and `workspace_access` blockers;
|
|
124
|
-
- journal path;
|
|
125
|
-
- side effects proof, which must show all false values.
|
|
126
|
-
|
|
127
|
-
Stop after the report. This workflow never executes the action queue.
|
|
100
|
+
## G3 Verify
|
|
101
|
+
|
|
102
|
+
Verification is whole-row and bounded. The loop records planned -> did ->
|
|
103
|
+
outcome, then verifies before replanning.
|
|
104
|
+
|
|
105
|
+
- Own active prep jobs are reattached by `requestSource` and `requestHash`; do
|
|
106
|
+
not re-dispatch prep while the job is active.
|
|
107
|
+
- Foreign prep jobs are waited out or blocked as `foreign_prep_active`; their
|
|
108
|
+
outcomes are not adopted.
|
|
109
|
+
- Active enrichment/import work is handled by bounded packet rereads.
|
|
110
|
+
- The conversion verdict after the first prep batch is journaled from packet
|
|
111
|
+
facts. The plan gate withholds a second unproven prep batch when
|
|
112
|
+
`censusReason` is `conversion_blocked`.
|
|
113
|
+
- Honest rubric failure means a human updates the rubric or changes lead source.
|
|
114
|
+
- Capped scheduler capacity is complete.
|
|
115
|
+
|
|
116
|
+
Scheduler wait is cross-invocation. If the tool returns `in_progress` with
|
|
117
|
+
sweep guidance, re-invoke `refill_sends_v2` with `{runId, fence}`. The scheduler
|
|
118
|
+
budget is cumulative at the run level. Zero pickup after a confirmed sweep is
|
|
119
|
+
debugged from `pipelineDiagnosis`; it is not waited out forever.
|
|
120
|
+
|
|
121
|
+
## G4 Report
|
|
122
|
+
|
|
123
|
+
Completion proof is the run record at `g4_terminal` with a named doneReason and
|
|
124
|
+
journal evidence showing planned -> did -> outcome plus a terminal block and
|
|
125
|
+
index line. A plan packet alone is not completion proof.
|
|
126
|
+
|
|
127
|
+
Terminal reasons are `complete`, `capped_by_scheduler`,
|
|
128
|
+
`loaded_awaiting_scheduler`, `lanes_exhausted`, `blocked`,
|
|
129
|
+
`no_refillable_campaigns`, and `not_an_evergreen_workspace`.
|
|
130
|
+
|
|
131
|
+
`loaded_awaiting_scheduler` remains the run-record token, but report copy must
|
|
132
|
+
include remaining-ready count, exact expected pickup time, and the resume
|
|
133
|
+
handle. Do not render bare "loaded, awaiting scheduler" as a final answer.
|
|
134
|
+
|
|
135
|
+
Report campaign names and sender names first, ids second. Include lane source,
|
|
136
|
+
lane chain, chosen label with token secondary, plan revision, terminal reason or
|
|
137
|
+
resume handle, journal path, blocked continuation packets, and firstFailing
|
|
138
|
+
checklist when present.
|