@sellable/install 0.1.215 → 0.1.217
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/README.md +12 -13
- package/bin/sellable-install.mjs +98 -112
- package/package.json +1 -1
- package/skill-templates/create-campaign.md +16 -3
package/README.md
CHANGED
|
@@ -31,12 +31,13 @@ agent command for launching a campaign:
|
|
|
31
31
|
sellable create
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
Campaign creation, foundation memory, content capture/ideation, post
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
Campaign creation, foundation memory, content capture/ideation, and post
|
|
35
|
+
drafting run inside Claude Code or Codex, where the Sellable MCP tools and
|
|
36
|
+
approval flows are available.
|
|
37
37
|
|
|
38
|
-
Install is auth-free by default.
|
|
39
|
-
Sellable
|
|
38
|
+
Install is auth-free by default. The normal path is first-run login: launch a
|
|
39
|
+
Sellable workflow in Claude Code or Codex and the agent handles Sellable
|
|
40
|
+
sign-in with a browser magic-link handoff.
|
|
40
41
|
|
|
41
42
|
The installer uses package stdio MCP by default:
|
|
42
43
|
|
|
@@ -64,14 +65,15 @@ verification in one path:
|
|
|
64
65
|
curl -fsSL "https://app.sellable.dev/api/v2/cli/install" | sh
|
|
65
66
|
```
|
|
66
67
|
|
|
67
|
-
For
|
|
68
|
+
For scripted fallback after browser login, paste the command shown by Sellable:
|
|
68
69
|
|
|
69
|
-
```
|
|
70
|
-
|
|
70
|
+
```bash
|
|
71
|
+
sellable auth set <token> --workspace-id <workspace_id>
|
|
71
72
|
```
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
`SELLABLE_WORKSPACE_ID`.
|
|
74
|
+
For CI/env-only installs, operators can still pass `--token` / `SELLABLE_TOKEN`
|
|
75
|
+
plus `--workspace-id` / `SELLABLE_WORKSPACE_ID`. Do not use env vars as the
|
|
76
|
+
primary human setup path.
|
|
75
77
|
|
|
76
78
|
Auth is stored once at:
|
|
77
79
|
|
|
@@ -97,20 +99,17 @@ Use the same public entrypoints in both hosts:
|
|
|
97
99
|
- Claude Code: `/sellable:foundation`
|
|
98
100
|
- Claude Code: `/sellable:content`
|
|
99
101
|
- Claude Code: `/sellable:create-post`
|
|
100
|
-
- Claude Code: `/sellable:inbox`
|
|
101
102
|
- Codex: `$sellable:create-campaign`
|
|
102
103
|
- Codex: `$sellable:create-ab-test`
|
|
103
104
|
- Codex: `$sellable:foundation`
|
|
104
105
|
- Codex: `$sellable:content`
|
|
105
106
|
- Codex: `$sellable:create-post`
|
|
106
|
-
- Codex: `$sellable:inbox`
|
|
107
107
|
- Codex Desktop plugin: `sellable@sellable`
|
|
108
108
|
- Codex visible skill: `Sellable Create Campaign`
|
|
109
109
|
- Codex visible skill: `Sellable Create A/B Test`
|
|
110
110
|
- Codex visible skill: `Sellable Foundation`
|
|
111
111
|
- Codex visible skill: `Sellable Content`
|
|
112
112
|
- Codex visible skill: `Sellable Create Post`
|
|
113
|
-
- Codex visible skill: `Sellable Inbox`
|
|
114
113
|
- Internal MCP workflow prompt: `create-campaign-v2`
|
|
115
114
|
- Internal/backward-compatible memory prompt: `interview`
|
|
116
115
|
|
package/bin/sellable-install.mjs
CHANGED
|
@@ -182,7 +182,7 @@ Options:
|
|
|
182
182
|
|
|
183
183
|
Auth:
|
|
184
184
|
Install is auth-free by default. Sign in happens on the first run of
|
|
185
|
-
/sellable:create-campaign, /sellable:foundation, /sellable:content, /sellable:create-post
|
|
185
|
+
/sellable:create-campaign, /sellable:foundation, /sellable:content, or /sellable:create-post in Claude Code or Codex,
|
|
186
186
|
where the agent walks you through signup or sign-in and stores credentials
|
|
187
187
|
in ~/.sellable/config.json.
|
|
188
188
|
|
|
@@ -211,7 +211,6 @@ function printCreateCommandHint() {
|
|
|
211
211
|
{ label: "Foundation", command: "/sellable:foundation" },
|
|
212
212
|
{ label: "Content", command: "/sellable:content" },
|
|
213
213
|
{ label: "Post", command: "/sellable:create-post" },
|
|
214
|
-
{ label: "Inbox", command: "/sellable:inbox" },
|
|
215
214
|
]);
|
|
216
215
|
console.log("");
|
|
217
216
|
console.log("");
|
|
@@ -221,7 +220,6 @@ function printCreateCommandHint() {
|
|
|
221
220
|
{ label: "Foundation", command: "$sellable:foundation" },
|
|
222
221
|
{ label: "Content", command: "$sellable:content" },
|
|
223
222
|
{ label: "Post", command: "$sellable:create-post" },
|
|
224
|
-
{ label: "Inbox", command: "$sellable:inbox" },
|
|
225
223
|
]);
|
|
226
224
|
console.log("");
|
|
227
225
|
console.log(` ${"─".repeat(63)}`);
|
|
@@ -421,13 +419,26 @@ async function loadAuthIfPresent(opts) {
|
|
|
421
419
|
return opts;
|
|
422
420
|
}
|
|
423
421
|
|
|
422
|
+
function redactTokensForLog(value) {
|
|
423
|
+
if (Array.isArray(value)) {
|
|
424
|
+
return value.map((item) => redactTokensForLog(item));
|
|
425
|
+
}
|
|
426
|
+
if (value && typeof value === "object") {
|
|
427
|
+
return Object.fromEntries(
|
|
428
|
+
Object.entries(value).map(([key, item]) => [
|
|
429
|
+
key,
|
|
430
|
+
key.toLowerCase().includes("token") && typeof item === "string"
|
|
431
|
+
? redact(item)
|
|
432
|
+
: redactTokensForLog(item),
|
|
433
|
+
])
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
return value;
|
|
437
|
+
}
|
|
438
|
+
|
|
424
439
|
function writeJson(path, data, opts) {
|
|
425
440
|
if (VERBOSE) {
|
|
426
|
-
const redacted = JSON.stringify(
|
|
427
|
-
{ ...data, token: redact(data.token) },
|
|
428
|
-
null,
|
|
429
|
-
2
|
|
430
|
-
);
|
|
441
|
+
const redacted = JSON.stringify(redactTokensForLog(data), null, 2);
|
|
431
442
|
logVerbose(`${C.grey}Writing ${path}: ${redacted}${C.reset}`);
|
|
432
443
|
}
|
|
433
444
|
if (opts.dryRun) return;
|
|
@@ -444,6 +455,56 @@ function readExisting(path) {
|
|
|
444
455
|
}
|
|
445
456
|
}
|
|
446
457
|
|
|
458
|
+
function mergeAuthConfig(raw, auth) {
|
|
459
|
+
const existing =
|
|
460
|
+
raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
461
|
+
const authFields = {
|
|
462
|
+
token: auth.token,
|
|
463
|
+
activeWorkspaceId: auth.activeWorkspaceId,
|
|
464
|
+
apiUrl: auth.apiUrl,
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
if (existing.activeEnv && existing.environments) {
|
|
468
|
+
const activeEnv = existing.activeEnv;
|
|
469
|
+
const envConfig = existing.environments[activeEnv];
|
|
470
|
+
if (
|
|
471
|
+
!envConfig ||
|
|
472
|
+
typeof envConfig !== "object" ||
|
|
473
|
+
Array.isArray(envConfig)
|
|
474
|
+
) {
|
|
475
|
+
throw new Error(
|
|
476
|
+
`Unknown active environment '${activeEnv}' in ${authPath()}`
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
return {
|
|
480
|
+
...existing,
|
|
481
|
+
environments: {
|
|
482
|
+
...existing.environments,
|
|
483
|
+
[activeEnv]: {
|
|
484
|
+
...envConfig,
|
|
485
|
+
...authFields,
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return {
|
|
492
|
+
...existing,
|
|
493
|
+
...authFields,
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function writeAuthSetConfig({ token, workspaceId, apiUrl, dryRun }) {
|
|
498
|
+
const configPath = authPath();
|
|
499
|
+
const raw = readExisting(configPath) || {};
|
|
500
|
+
const config = mergeAuthConfig(raw, {
|
|
501
|
+
token,
|
|
502
|
+
activeWorkspaceId: workspaceId || null,
|
|
503
|
+
apiUrl,
|
|
504
|
+
});
|
|
505
|
+
writeJson(configPath, config, { dryRun });
|
|
506
|
+
}
|
|
507
|
+
|
|
447
508
|
function sellableHostEnvPath() {
|
|
448
509
|
return join(homedir(), ".local", "sellable", "app-sellable-dev", ".env");
|
|
449
510
|
}
|
|
@@ -743,6 +804,7 @@ const CREATE_CAMPAIGN_ALLOWED_TOOLS = [
|
|
|
743
804
|
"mcp__sellable__select_campaign_cells",
|
|
744
805
|
"mcp__sellable__queue_campaign_cells",
|
|
745
806
|
"mcp__sellable__wait_for_campaign_processing",
|
|
807
|
+
"mcp__sellable__fill_campaign_horizon",
|
|
746
808
|
"mcp__sellable__start_campaign_message_preparation",
|
|
747
809
|
"mcp__sellable__get_campaign_message_preparation_status",
|
|
748
810
|
"mcp__sellable__cancel_campaign_message_preparation",
|
|
@@ -1755,67 +1817,6 @@ then retry \`get_subskill_prompt\`.
|
|
|
1755
1817
|
`, host, "create-post");
|
|
1756
1818
|
}
|
|
1757
1819
|
|
|
1758
|
-
function inboxSkillMd(host = "shared") {
|
|
1759
|
-
return stampInstalledHost(`---
|
|
1760
|
-
name: inbox
|
|
1761
|
-
description: Search Sellable inbox threads, review reply eligibility, and manage approval-gated LinkedIn replies.
|
|
1762
|
-
allowed-tools:
|
|
1763
|
-
- mcp__sellable__get_auth_status
|
|
1764
|
-
- mcp__sellable__search_inbox_threads
|
|
1765
|
-
- mcp__sellable__get_inbox_thread
|
|
1766
|
-
- mcp__sellable__check_inbox_reply_eligibility
|
|
1767
|
-
- mcp__sellable__update_inbox_draft
|
|
1768
|
-
- mcp__sellable__send_inbox_draft
|
|
1769
|
-
- mcp__sellable__send_inbox_manual_reply
|
|
1770
|
-
---
|
|
1771
|
-
|
|
1772
|
-
# Sellable Inbox
|
|
1773
|
-
|
|
1774
|
-
Use this as the customer-facing entrypoint for Sellable inbox reply management.
|
|
1775
|
-
It can search LinkedIn inbox threads, load thread history, check product reply
|
|
1776
|
-
eligibility, update an existing draft, send an approved draft, or send one exact
|
|
1777
|
-
manual reply.
|
|
1778
|
-
|
|
1779
|
-
## Bootstrap
|
|
1780
|
-
|
|
1781
|
-
MCP tool access is required. First call \`mcp__sellable__get_auth_status({})\`.
|
|
1782
|
-
Do not inspect repo files, run shell commands, use \`npm\`, \`node\`, local
|
|
1783
|
-
harness scripts, browser automation, or product API routes to emulate this
|
|
1784
|
-
workflow.
|
|
1785
|
-
|
|
1786
|
-
If the Sellable MCP tool is unavailable, stop and say this is a Codex
|
|
1787
|
-
install/reload problem. Tell the user to run
|
|
1788
|
-
\`curl -fsSL "https://app.sellable.dev/api/v2/cli/install" | sh\`, fully quit and reopen Codex
|
|
1789
|
-
Desktop, then start a new thread.
|
|
1790
|
-
|
|
1791
|
-
## Read Workflow
|
|
1792
|
-
|
|
1793
|
-
1. Call \`mcp__sellable__get_auth_status({})\`.
|
|
1794
|
-
2. Use \`mcp__sellable__search_inbox_threads({ limit, search?, filter?, status?, senderId?, classification?, includeReplyEligibility? })\` to find candidate threads.
|
|
1795
|
-
3. Use \`mcp__sellable__get_inbox_thread({ threadId })\` before summarizing or drafting.
|
|
1796
|
-
4. Use \`mcp__sellable__check_inbox_reply_eligibility({ threadId })\` before proposing any reply send path.
|
|
1797
|
-
|
|
1798
|
-
## Approval Gates
|
|
1799
|
-
|
|
1800
|
-
Never call \`mcp__sellable__update_inbox_draft\`,
|
|
1801
|
-
\`mcp__sellable__send_inbox_draft\`, or
|
|
1802
|
-
\`mcp__sellable__send_inbox_manual_reply\` until the user has explicitly
|
|
1803
|
-
approved all of:
|
|
1804
|
-
|
|
1805
|
-
- workspace/account context
|
|
1806
|
-
- sender
|
|
1807
|
-
- thread or recipient
|
|
1808
|
-
- exact body
|
|
1809
|
-
- exact tool to call
|
|
1810
|
-
- expected side effect
|
|
1811
|
-
|
|
1812
|
-
Draft edits only edit an existing draft. They do not create a new reply draft.
|
|
1813
|
-
Send tools support one thread at a time; do not batch sends. If any approval,
|
|
1814
|
-
snapshot, hash, version, eligibility, or idempotency value is missing or stale,
|
|
1815
|
-
stop and re-read the thread instead of guessing.
|
|
1816
|
-
`, host, "inbox");
|
|
1817
|
-
}
|
|
1818
|
-
|
|
1819
1820
|
function createCampaignSoulMd() {
|
|
1820
1821
|
return `# Sellable Campaign GTM Engineer Soul
|
|
1821
1822
|
|
|
@@ -2037,12 +2038,6 @@ function codexPluginSkills() {
|
|
|
2037
2038
|
description: "Capture ideas and draft LinkedIn posts in your voice",
|
|
2038
2039
|
skillMd: createPostSkillMd(),
|
|
2039
2040
|
},
|
|
2040
|
-
{
|
|
2041
|
-
dir: "sellable-inbox",
|
|
2042
|
-
displayName: "Sellable Inbox",
|
|
2043
|
-
description: "Search and manage approval-gated LinkedIn inbox replies",
|
|
2044
|
-
skillMd: inboxSkillMd(),
|
|
2045
|
-
},
|
|
2046
2041
|
];
|
|
2047
2042
|
}
|
|
2048
2043
|
|
|
@@ -2268,23 +2263,6 @@ function claudeCommands() {
|
|
|
2268
2263
|
argumentHint: "[post idea or source material]",
|
|
2269
2264
|
skillMd: createPostSkillMd(),
|
|
2270
2265
|
},
|
|
2271
|
-
{
|
|
2272
|
-
name: "inbox",
|
|
2273
|
-
title: "Inbox",
|
|
2274
|
-
filename: join("sellable", "inbox.md"),
|
|
2275
|
-
description: "Search and manage approval-gated Sellable inbox replies.",
|
|
2276
|
-
argumentHint: "[thread, sender, recipient, or reply goal]",
|
|
2277
|
-
skillMd: inboxSkillMd(),
|
|
2278
|
-
allowedTools: [
|
|
2279
|
-
"mcp__sellable__get_auth_status",
|
|
2280
|
-
"mcp__sellable__search_inbox_threads",
|
|
2281
|
-
"mcp__sellable__get_inbox_thread",
|
|
2282
|
-
"mcp__sellable__check_inbox_reply_eligibility",
|
|
2283
|
-
"mcp__sellable__update_inbox_draft",
|
|
2284
|
-
"mcp__sellable__send_inbox_draft",
|
|
2285
|
-
"mcp__sellable__send_inbox_manual_reply",
|
|
2286
|
-
],
|
|
2287
|
-
},
|
|
2288
2266
|
].map((command) => ({
|
|
2289
2267
|
...command,
|
|
2290
2268
|
content: claudeCommandMd(command),
|
|
@@ -3508,7 +3486,6 @@ function printNextSteps(installedHosts, authReused) {
|
|
|
3508
3486
|
{ label: "Foundation", command: "/sellable:foundation" },
|
|
3509
3487
|
{ label: "Content", command: "/sellable:content" },
|
|
3510
3488
|
{ label: "Post", command: "/sellable:create-post" },
|
|
3511
|
-
{ label: "Inbox", command: "/sellable:inbox" },
|
|
3512
3489
|
]);
|
|
3513
3490
|
console.log("");
|
|
3514
3491
|
console.log("");
|
|
@@ -3519,7 +3496,6 @@ function printNextSteps(installedHosts, authReused) {
|
|
|
3519
3496
|
{ label: "Foundation", command: "$sellable:foundation" },
|
|
3520
3497
|
{ label: "Content", command: "$sellable:content" },
|
|
3521
3498
|
{ label: "Post", command: "$sellable:create-post" },
|
|
3522
|
-
{ label: "Inbox", command: "$sellable:inbox" },
|
|
3523
3499
|
]);
|
|
3524
3500
|
console.log("");
|
|
3525
3501
|
}
|
|
@@ -3752,18 +3728,31 @@ async function main() {
|
|
|
3752
3728
|
}
|
|
3753
3729
|
const token = rawArgs[2];
|
|
3754
3730
|
const authSetFlags = rawArgs.slice(3);
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3731
|
+
let dryRun = false;
|
|
3732
|
+
let workspaceId = "";
|
|
3733
|
+
for (let i = 0; i < authSetFlags.length; i += 1) {
|
|
3734
|
+
const flag = authSetFlags[i];
|
|
3735
|
+
if (flag === "--dry-run") {
|
|
3736
|
+
dryRun = true;
|
|
3737
|
+
continue;
|
|
3738
|
+
}
|
|
3739
|
+
if (flag === "--workspace-id") {
|
|
3740
|
+
const value = authSetFlags[i + 1];
|
|
3741
|
+
if (!value || value.startsWith("--")) {
|
|
3742
|
+
console.error("Missing value for --workspace-id");
|
|
3743
|
+
process.exit(2);
|
|
3744
|
+
}
|
|
3745
|
+
workspaceId = value;
|
|
3746
|
+
i += 1;
|
|
3747
|
+
continue;
|
|
3748
|
+
}
|
|
3749
|
+
console.error(`Unknown auth set option: ${flag}`);
|
|
3761
3750
|
process.exit(2);
|
|
3762
3751
|
}
|
|
3763
3752
|
if (!token) {
|
|
3764
3753
|
console.error(
|
|
3765
|
-
"Usage: sellable auth set <token
|
|
3766
|
-
"
|
|
3754
|
+
"Usage: sellable auth set <token> [--workspace-id <id>]\n" +
|
|
3755
|
+
"Use this only when the Sellable browser login page shows a manual fallback command."
|
|
3767
3756
|
);
|
|
3768
3757
|
process.exit(2);
|
|
3769
3758
|
}
|
|
@@ -3775,34 +3764,31 @@ async function main() {
|
|
|
3775
3764
|
);
|
|
3776
3765
|
process.exit(2);
|
|
3777
3766
|
}
|
|
3778
|
-
// Bypass writeAuth()
|
|
3779
|
-
//
|
|
3780
|
-
//
|
|
3767
|
+
// Bypass writeAuth() because auth-set is a first-run browser fallback:
|
|
3768
|
+
// the workspace id is optional for legacy fallback pages, and existing
|
|
3769
|
+
// config metadata must be preserved.
|
|
3781
3770
|
// Skip installSelfShim() — by definition the user has the shim already
|
|
3782
3771
|
// (they invoked `sellable auth set` from it).
|
|
3783
3772
|
const apiUrl = process.env.SELLABLE_API_URL || DEFAULT_API_URL;
|
|
3784
|
-
|
|
3785
|
-
authPath(),
|
|
3786
|
-
{ token, activeWorkspaceId: null, apiUrl },
|
|
3787
|
-
{ dryRun }
|
|
3788
|
-
);
|
|
3773
|
+
writeAuthSetConfig({ token, workspaceId, apiUrl, dryRun });
|
|
3789
3774
|
if (dryRun) {
|
|
3790
3775
|
console.log(`Dry run: token would be saved to ${authPath()}`);
|
|
3791
3776
|
} else {
|
|
3792
3777
|
console.log(`✓ Token saved to ${authPath()}`);
|
|
3793
3778
|
}
|
|
3794
3779
|
console.log(` apiUrl: ${apiUrl}`);
|
|
3780
|
+
if (workspaceId) {
|
|
3781
|
+
console.log(` activeWorkspaceId: ${workspaceId}`);
|
|
3782
|
+
}
|
|
3795
3783
|
console.log(` Continue in your agent:`);
|
|
3796
3784
|
console.log(` Claude Code: /sellable:create-campaign`);
|
|
3797
3785
|
console.log(` Claude Code: /sellable:foundation`);
|
|
3798
3786
|
console.log(` Claude Code: /sellable:content`);
|
|
3799
3787
|
console.log(` Claude Code: /sellable:create-post`);
|
|
3800
|
-
console.log(` Claude Code: /sellable:inbox`);
|
|
3801
3788
|
console.log(` Codex: $sellable:create-campaign`);
|
|
3802
3789
|
console.log(` Codex: $sellable:foundation`);
|
|
3803
3790
|
console.log(` Codex: $sellable:content`);
|
|
3804
3791
|
console.log(` Codex: $sellable:create-post`);
|
|
3805
|
-
console.log(` Codex: $sellable:inbox`);
|
|
3806
3792
|
process.exit(0);
|
|
3807
3793
|
}
|
|
3808
3794
|
if (rawArgs[0] === "prefs") {
|
package/package.json
CHANGED
|
@@ -46,6 +46,7 @@ allowed-tools:
|
|
|
46
46
|
- mcp__sellable__select_campaign_cells
|
|
47
47
|
- mcp__sellable__queue_campaign_cells
|
|
48
48
|
- mcp__sellable__wait_for_campaign_processing
|
|
49
|
+
- mcp__sellable__fill_campaign_horizon
|
|
49
50
|
- mcp__sellable__start_campaign_message_preparation
|
|
50
51
|
- mcp__sellable__get_campaign_message_preparation_status
|
|
51
52
|
- mcp__sellable__cancel_campaign_message_preparation
|
|
@@ -107,6 +108,13 @@ the template is approved.
|
|
|
107
108
|
The default path stays the existing first campaign-table execution slice:
|
|
108
109
|
review the normal `reviewBatchLimit:15`, approve reviewed draft rows, then move
|
|
109
110
|
to Settings/sequence/final greenlight. Only call
|
|
111
|
+
`fill_campaign_horizon` for explicit source-cleanup horizon-fill requests, such
|
|
112
|
+
as "fill sends from Signal Discovery but not John Cutler posts." Run
|
|
113
|
+
`fill_campaign_horizon({ action:"audit", ... })` first, then apply with the
|
|
114
|
+
returned `stateRevision`. It imports/prepares at most 300 eligible non-excluded
|
|
115
|
+
source rows in the first pass, caps prep batches at 100, skips existing rows
|
|
116
|
+
from excluded post/author sources, and does not launch the campaign. If the
|
|
117
|
+
user only asks for generic extra sends with no source cleanup, use
|
|
110
118
|
`start_campaign_message_preparation` when the user explicitly asks for more
|
|
111
119
|
prepared messages, a send count, or language like "fill up/load sends for these
|
|
112
120
|
senders." Treat those requests as capacity-fill preparation: calculate the
|
|
@@ -120,8 +128,9 @@ count `checkedRows` as enriched rows; it is only the table cursor. Use
|
|
|
120
128
|
messages", set `targetPreparedMessages:X`, omit `maxRowsToCheck`, and keep
|
|
121
129
|
`approvalMode:"mark_ready"`. The backend calibrates on at least 100 actually
|
|
122
130
|
enriched rows, estimates the row budget from observed rubric/pass yield, caps
|
|
123
|
-
`maxRowsToCheck` at
|
|
124
|
-
|
|
131
|
+
`maxRowsToCheck` at 300, then continues in batches capped at 100 newly checked
|
|
132
|
+
rows. It will not pull another row batch while the current checked batch still
|
|
133
|
+
has queueable or active cells. If the user says "approve X messages", use
|
|
125
134
|
`approvalMode:"approve"` but still do not launch. If the user says "schedule X
|
|
126
135
|
sends" or asks to fill sender sends, use `approvalMode:"approve"` to approve
|
|
127
136
|
exactly the bounded X-message cohort during preparation, then continue through
|
|
@@ -884,7 +893,11 @@ updates.
|
|
|
884
893
|
|
|
885
894
|
1. Call `mcp__sellable__get_auth_status({})`.
|
|
886
895
|
2. If auth is not OK with `error.type === "config"` or `error.type === "auth"`,
|
|
887
|
-
the user has not signed in yet. Run the FTUX
|
|
896
|
+
the user has not signed in yet. Run first-run login through the FTUX
|
|
897
|
+
magic-link handoff. If a browser page or tool guidance gives the user a
|
|
898
|
+
manual fallback, it must be
|
|
899
|
+
`sellable auth set <token> --workspace-id <workspace_id>`. Do not instruct
|
|
900
|
+
the user to hand-edit JSON auth config.
|
|
888
901
|
|
|
889
902
|
a. Say to the user verbatim:
|
|
890
903
|
|