@sellable/install 0.1.317 → 0.1.318
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/agents/registry.json +2 -2
- package/bin/sellable-install.mjs +3 -3
- package/lib/runtime-verify.mjs +249 -40
- package/package.json +1 -1
- package/skill-templates/create-campaign.md +3 -3
- package/skill-templates/create-evergreen-campaigns.md +73 -24
- package/skill-templates/refill-sends-v2.md +5 -0
- package/skill-templates/refill-sends.md +5 -0
package/agents/registry.json
CHANGED
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"ownership": "message strategy, proof inventory, token rules, skeptical-prospect review, and selected winner only",
|
|
27
27
|
"codex": {
|
|
28
28
|
"description": "Message Drafting worker for campaign-backed template proposals after confirm_lead_list imports a non-empty bounded review batch.",
|
|
29
|
-
"model": "gpt-5.
|
|
30
|
-
"modelReasoningEffort": "
|
|
29
|
+
"model": "gpt-5.6-sol",
|
|
30
|
+
"modelReasoningEffort": "high",
|
|
31
31
|
"sandboxMode": "read-only",
|
|
32
32
|
"nicknameCandidates": [
|
|
33
33
|
"Message Drafting",
|
package/bin/sellable-install.mjs
CHANGED
|
@@ -1660,7 +1660,7 @@ Treat host capabilities as concrete functions, not prose conventions:
|
|
|
1660
1660
|
import and before dispatching Message Drafting only.
|
|
1661
1661
|
- \`launch_message_drafting\`: Claude Code uses \`Task\` with \`subagent_type\`
|
|
1662
1662
|
\`post-find-leads-message-scout\` when listed; Codex uses the returned
|
|
1663
|
-
compatibility agent or a generic \`gpt-5.
|
|
1663
|
+
compatibility agent or a generic \`gpt-5.6-sol\` / \`high\` Message Drafting agent.
|
|
1664
1664
|
|
|
1665
1665
|
If a required interactive question function or MCP loader is missing, stop and
|
|
1666
1666
|
explain the Sellable install/reload problem. Source and filter work use
|
|
@@ -3057,8 +3057,8 @@ function generateCodexAgentToml(agent) {
|
|
|
3057
3057
|
const codex = agent.codex;
|
|
3058
3058
|
return `name = ${quoteToml(agent.name)}
|
|
3059
3059
|
description = ${quoteToml(codex.description)}
|
|
3060
|
-
model = ${quoteToml(codex.model || "gpt-5.
|
|
3061
|
-
model_reasoning_effort = ${quoteToml(codex.modelReasoningEffort || "
|
|
3060
|
+
model = ${quoteToml(codex.model || "gpt-5.6-sol")}
|
|
3061
|
+
model_reasoning_effort = ${quoteToml(codex.modelReasoningEffort || "high")}
|
|
3062
3062
|
sandbox_mode = ${quoteToml(codex.sandboxMode || "read-only")}
|
|
3063
3063
|
nickname_candidates = ${tomlArray(codex.nicknameCandidates || [agent.displayName])}
|
|
3064
3064
|
developer_instructions = ${tomlMultilineString(agent.prompt)}
|
package/lib/runtime-verify.mjs
CHANGED
|
@@ -45,6 +45,14 @@ export const REQUIRED_SELLABLE_MCP_TOOLS = [
|
|
|
45
45
|
|
|
46
46
|
export const FORBIDDEN_SELLABLE_MCP_TOOLS = ["refill_campaign_sends"];
|
|
47
47
|
|
|
48
|
+
const CONNECTION_ONLY_EVERGREEN_PROMPT_CHUNK_LIMIT = 48_000;
|
|
49
|
+
const CONNECTION_ONLY_EVERGREEN_MAX_PROMPT_CHUNKS = 8;
|
|
50
|
+
const CONNECTION_ONLY_EVERGREEN_PROOF_NEEDLES = {
|
|
51
|
+
campaignSequenceOptions: 'campaignSequenceOptions:{ mode:"connection_only" }',
|
|
52
|
+
templateRef: 'templateRef:"connection_only"',
|
|
53
|
+
sendInviteReceipt: 'sequenceReceipt.actionTypes:["send_invite"]',
|
|
54
|
+
};
|
|
55
|
+
|
|
48
56
|
export const CREATE_CAMPAIGN_SMOKE_CALLS = [
|
|
49
57
|
{
|
|
50
58
|
name: "get_auth_status",
|
|
@@ -84,6 +92,14 @@ export const CREATE_CAMPAIGN_SMOKE_CALLS = [
|
|
|
84
92
|
limit: 1200,
|
|
85
93
|
},
|
|
86
94
|
},
|
|
95
|
+
{
|
|
96
|
+
name: "get_subskill_prompt",
|
|
97
|
+
arguments: {
|
|
98
|
+
subskillName: "create-evergreen-campaigns",
|
|
99
|
+
offset: 0,
|
|
100
|
+
limit: CONNECTION_ONLY_EVERGREEN_PROMPT_CHUNK_LIMIT,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
87
103
|
{
|
|
88
104
|
name: "refill_sends",
|
|
89
105
|
arguments: {
|
|
@@ -187,6 +203,43 @@ function parseJsonText(text) {
|
|
|
187
203
|
}
|
|
188
204
|
}
|
|
189
205
|
|
|
206
|
+
function emptyConnectionOnlyEvergreenProofs() {
|
|
207
|
+
return Object.fromEntries(
|
|
208
|
+
Object.keys(CONNECTION_ONLY_EVERGREEN_PROOF_NEEDLES).map((key) => [
|
|
209
|
+
key,
|
|
210
|
+
false,
|
|
211
|
+
])
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function getConnectionOnlyEvergreenProofs(prompt) {
|
|
216
|
+
return Object.fromEntries(
|
|
217
|
+
Object.entries(CONNECTION_ONLY_EVERGREEN_PROOF_NEEDLES).map(
|
|
218
|
+
([key, needle]) => [key, prompt.includes(needle)]
|
|
219
|
+
)
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function mergeConnectionOnlyEvergreenProofs(target, source) {
|
|
224
|
+
if (!source) return target;
|
|
225
|
+
for (const key of Object.keys(CONNECTION_ONLY_EVERGREEN_PROOF_NEEDLES)) {
|
|
226
|
+
target[key] = target[key] === true || source[key] === true;
|
|
227
|
+
}
|
|
228
|
+
return target;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function summarizeConnectionOnlyEvergreenProofs(proofs) {
|
|
232
|
+
const merged = { ...emptyConnectionOnlyEvergreenProofs(), ...(proofs || {}) };
|
|
233
|
+
const missing = Object.keys(CONNECTION_ONLY_EVERGREEN_PROOF_NEEDLES).filter(
|
|
234
|
+
(key) => merged[key] !== true
|
|
235
|
+
);
|
|
236
|
+
return {
|
|
237
|
+
ok: missing.length === 0,
|
|
238
|
+
proofs: merged,
|
|
239
|
+
missing,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
190
243
|
function summarizeToolResult(name, result) {
|
|
191
244
|
const text = redact(textFromToolResult(result));
|
|
192
245
|
const parsed = parseJsonText(text);
|
|
@@ -230,10 +283,26 @@ function summarizeToolResult(name, result) {
|
|
|
230
283
|
}
|
|
231
284
|
|
|
232
285
|
if (name === "get_subskill_prompt" && parsed) {
|
|
286
|
+
const prompt = typeof parsed.prompt === "string" ? parsed.prompt : "";
|
|
287
|
+
const connectionOnlyEvergreenProofs =
|
|
288
|
+
parsed.name === "create-evergreen-campaigns"
|
|
289
|
+
? getConnectionOnlyEvergreenProofs(prompt)
|
|
290
|
+
: null;
|
|
233
291
|
return {
|
|
234
292
|
...summary,
|
|
235
293
|
subskillName: parsed.name || null,
|
|
236
|
-
promptChars:
|
|
294
|
+
promptChars: prompt.length,
|
|
295
|
+
promptLength:
|
|
296
|
+
typeof parsed.promptLength === "number" ? parsed.promptLength : null,
|
|
297
|
+
offset: typeof parsed.offset === "number" ? parsed.offset : null,
|
|
298
|
+
limit: typeof parsed.limit === "number" ? parsed.limit : null,
|
|
299
|
+
connectionOnlyEvergreenProofs,
|
|
300
|
+
connectionOnlyEvergreenGuidance:
|
|
301
|
+
parsed.name === "create-evergreen-campaigns"
|
|
302
|
+
? summarizeConnectionOnlyEvergreenProofs(
|
|
303
|
+
connectionOnlyEvergreenProofs
|
|
304
|
+
).ok
|
|
305
|
+
: null,
|
|
237
306
|
hasMore: parsed.hasMore === true,
|
|
238
307
|
nextOffset:
|
|
239
308
|
typeof parsed.nextOffset === "number" ? parsed.nextOffset : null,
|
|
@@ -267,6 +336,7 @@ async function verifyCreateCampaignSmoke({
|
|
|
267
336
|
.map((call) => call.name)
|
|
268
337
|
.filter((name) => !available.has(name));
|
|
269
338
|
const calls = [];
|
|
339
|
+
const connectionOnlyEvergreenProofs = emptyConnectionOnlyEvergreenProofs();
|
|
270
340
|
|
|
271
341
|
if (missingTools.length > 0) {
|
|
272
342
|
return {
|
|
@@ -280,67 +350,195 @@ async function verifyCreateCampaignSmoke({
|
|
|
280
350
|
}
|
|
281
351
|
|
|
282
352
|
for (const call of smokeCalls) {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
353
|
+
let nextCall = call;
|
|
354
|
+
let evergreenPromptChunks = 0;
|
|
355
|
+
const evergreenPromptOffsets = new Set();
|
|
356
|
+
|
|
357
|
+
while (nextCall) {
|
|
358
|
+
const callStartedAt = new Date().toISOString();
|
|
359
|
+
try {
|
|
360
|
+
const result = await client.callTool(
|
|
361
|
+
{ name: nextCall.name, arguments: nextCall.arguments },
|
|
362
|
+
undefined,
|
|
363
|
+
{
|
|
364
|
+
timeout: timeoutMs,
|
|
365
|
+
maxTotalTimeout: timeoutMs,
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
const summary = summarizeToolResult(nextCall.name, result);
|
|
369
|
+
calls.push({
|
|
370
|
+
name: nextCall.name,
|
|
371
|
+
arguments: nextCall.arguments,
|
|
372
|
+
ok: summary.isError !== true,
|
|
373
|
+
summary,
|
|
374
|
+
startedAt: callStartedAt,
|
|
375
|
+
completedAt: new Date().toISOString(),
|
|
376
|
+
});
|
|
377
|
+
if (summary.isError === true) {
|
|
378
|
+
return {
|
|
379
|
+
ok: false,
|
|
380
|
+
missingTools: [],
|
|
381
|
+
calls,
|
|
382
|
+
error: `${nextCall.name} returned an MCP tool error`,
|
|
383
|
+
startedAt,
|
|
384
|
+
completedAt: new Date().toISOString(),
|
|
385
|
+
};
|
|
291
386
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
387
|
+
|
|
388
|
+
const isConnectionOnlyEvergreenPrompt =
|
|
389
|
+
nextCall.name === "get_subskill_prompt" &&
|
|
390
|
+
nextCall.arguments?.subskillName === "create-evergreen-campaigns";
|
|
391
|
+
if (!isConnectionOnlyEvergreenPrompt) {
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
evergreenPromptChunks += 1;
|
|
396
|
+
evergreenPromptOffsets.add(nextCall.arguments?.offset ?? 0);
|
|
397
|
+
mergeConnectionOnlyEvergreenProofs(
|
|
398
|
+
connectionOnlyEvergreenProofs,
|
|
399
|
+
summary.connectionOnlyEvergreenProofs
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
if (summary.hasMore !== true) {
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
if (typeof summary.nextOffset !== "number") {
|
|
406
|
+
return {
|
|
407
|
+
ok: false,
|
|
408
|
+
missingTools: [],
|
|
409
|
+
calls,
|
|
410
|
+
connectionOnlyEvergreenGuidance:
|
|
411
|
+
summarizeConnectionOnlyEvergreenProofs(
|
|
412
|
+
connectionOnlyEvergreenProofs
|
|
413
|
+
),
|
|
414
|
+
error:
|
|
415
|
+
"create-evergreen-campaigns prompt chunk is missing nextOffset",
|
|
416
|
+
startedAt,
|
|
417
|
+
completedAt: new Date().toISOString(),
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
if (evergreenPromptOffsets.has(summary.nextOffset)) {
|
|
421
|
+
return {
|
|
422
|
+
ok: false,
|
|
423
|
+
missingTools: [],
|
|
424
|
+
calls,
|
|
425
|
+
connectionOnlyEvergreenGuidance:
|
|
426
|
+
summarizeConnectionOnlyEvergreenProofs(
|
|
427
|
+
connectionOnlyEvergreenProofs
|
|
428
|
+
),
|
|
429
|
+
error:
|
|
430
|
+
"create-evergreen-campaigns prompt chunk repeated nextOffset",
|
|
431
|
+
startedAt,
|
|
432
|
+
completedAt: new Date().toISOString(),
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
if (
|
|
436
|
+
evergreenPromptChunks >= CONNECTION_ONLY_EVERGREEN_MAX_PROMPT_CHUNKS
|
|
437
|
+
) {
|
|
438
|
+
return {
|
|
439
|
+
ok: false,
|
|
440
|
+
missingTools: [],
|
|
441
|
+
calls,
|
|
442
|
+
connectionOnlyEvergreenGuidance:
|
|
443
|
+
summarizeConnectionOnlyEvergreenProofs(
|
|
444
|
+
connectionOnlyEvergreenProofs
|
|
445
|
+
),
|
|
446
|
+
error:
|
|
447
|
+
"create-evergreen-campaigns prompt exceeded smoke chunk limit",
|
|
448
|
+
startedAt,
|
|
449
|
+
completedAt: new Date().toISOString(),
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
nextCall = {
|
|
454
|
+
...nextCall,
|
|
455
|
+
arguments: {
|
|
456
|
+
...nextCall.arguments,
|
|
457
|
+
offset: summary.nextOffset,
|
|
458
|
+
limit:
|
|
459
|
+
nextCall.arguments?.limit ||
|
|
460
|
+
CONNECTION_ONLY_EVERGREEN_PROMPT_CHUNK_LIMIT,
|
|
461
|
+
},
|
|
462
|
+
};
|
|
463
|
+
} catch (err) {
|
|
464
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
465
|
+
calls.push({
|
|
466
|
+
name: nextCall.name,
|
|
467
|
+
arguments: nextCall.arguments,
|
|
468
|
+
ok: false,
|
|
469
|
+
summary: null,
|
|
470
|
+
error: redact(error),
|
|
471
|
+
startedAt: callStartedAt,
|
|
472
|
+
completedAt: new Date().toISOString(),
|
|
473
|
+
});
|
|
303
474
|
return {
|
|
304
475
|
ok: false,
|
|
305
476
|
missingTools: [],
|
|
306
477
|
calls,
|
|
307
|
-
error:
|
|
478
|
+
error: redact(error),
|
|
308
479
|
startedAt,
|
|
309
480
|
completedAt: new Date().toISOString(),
|
|
310
481
|
};
|
|
311
482
|
}
|
|
312
|
-
} catch (err) {
|
|
313
|
-
const error = err instanceof Error ? err.message : String(err);
|
|
314
|
-
calls.push({
|
|
315
|
-
name: call.name,
|
|
316
|
-
arguments: call.arguments,
|
|
317
|
-
ok: false,
|
|
318
|
-
summary: null,
|
|
319
|
-
error: redact(error),
|
|
320
|
-
startedAt: callStartedAt,
|
|
321
|
-
completedAt: new Date().toISOString(),
|
|
322
|
-
});
|
|
323
|
-
return {
|
|
324
|
-
ok: false,
|
|
325
|
-
missingTools: [],
|
|
326
|
-
calls,
|
|
327
|
-
error: redact(error),
|
|
328
|
-
startedAt,
|
|
329
|
-
completedAt: new Date().toISOString(),
|
|
330
|
-
};
|
|
331
483
|
}
|
|
332
484
|
}
|
|
333
485
|
|
|
486
|
+
const connectionOnlyEvergreenGuidance =
|
|
487
|
+
summarizeConnectionOnlyEvergreenProofs(connectionOnlyEvergreenProofs);
|
|
488
|
+
if (connectionOnlyEvergreenGuidance.ok !== true) {
|
|
489
|
+
return {
|
|
490
|
+
ok: false,
|
|
491
|
+
missingTools: [],
|
|
492
|
+
calls,
|
|
493
|
+
connectionOnlyEvergreenGuidance,
|
|
494
|
+
error: `create-evergreen-campaigns prompt is missing connection-only guidance: ${connectionOnlyEvergreenGuidance.missing.join(", ")}`,
|
|
495
|
+
startedAt,
|
|
496
|
+
completedAt: new Date().toISOString(),
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
334
500
|
return {
|
|
335
501
|
ok: true,
|
|
336
502
|
missingTools: [],
|
|
337
503
|
calls,
|
|
504
|
+
connectionOnlyEvergreenGuidance,
|
|
338
505
|
error: null,
|
|
339
506
|
startedAt,
|
|
340
507
|
completedAt: new Date().toISOString(),
|
|
341
508
|
};
|
|
342
509
|
}
|
|
343
510
|
|
|
511
|
+
function verifyConnectionOnlyEvergreenContract(tools) {
|
|
512
|
+
const setupTool = (tools || []).find(
|
|
513
|
+
(tool) => tool?.name === "setup_evergreen_campaigns"
|
|
514
|
+
);
|
|
515
|
+
const schema = setupTool?.inputSchema || {};
|
|
516
|
+
const properties = schema.properties || {};
|
|
517
|
+
const sequenceOptions = properties.campaignSequenceOptions || {};
|
|
518
|
+
const mode = sequenceOptions.properties?.mode || {};
|
|
519
|
+
const issues = [];
|
|
520
|
+
|
|
521
|
+
if (!properties.workspaceId) {
|
|
522
|
+
issues.push("setup_evergreen_campaigns.workspaceId");
|
|
523
|
+
}
|
|
524
|
+
if (!properties.campaignSequenceOptions) {
|
|
525
|
+
issues.push("setup_evergreen_campaigns.campaignSequenceOptions");
|
|
526
|
+
}
|
|
527
|
+
if (!Array.isArray(mode.enum) || !mode.enum.includes("connection_only")) {
|
|
528
|
+
issues.push("setup_evergreen_campaigns.campaignSequenceOptions.mode");
|
|
529
|
+
}
|
|
530
|
+
if (sequenceOptions.additionalProperties !== false) {
|
|
531
|
+
issues.push(
|
|
532
|
+
"setup_evergreen_campaigns.campaignSequenceOptions.additionalProperties"
|
|
533
|
+
);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
return {
|
|
537
|
+
ok: issues.length === 0,
|
|
538
|
+
issues,
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
|
|
344
542
|
function summarizeAttempt(result, attempt) {
|
|
345
543
|
return {
|
|
346
544
|
attempt,
|
|
@@ -348,6 +546,12 @@ function summarizeAttempt(result, attempt) {
|
|
|
348
546
|
availableToolCount: result.availableTools?.length || 0,
|
|
349
547
|
missingToolCount: result.missingTools?.length || 0,
|
|
350
548
|
forbiddenToolCount: result.forbiddenTools?.length || 0,
|
|
549
|
+
connectionOnlyEvergreenContract: result.connectionOnlyEvergreenContract
|
|
550
|
+
? {
|
|
551
|
+
ok: result.connectionOnlyEvergreenContract.ok === true,
|
|
552
|
+
issues: result.connectionOnlyEvergreenContract.issues || [],
|
|
553
|
+
}
|
|
554
|
+
: null,
|
|
351
555
|
error: result.error || null,
|
|
352
556
|
createCampaignSmoke: result.createCampaignSmoke
|
|
353
557
|
? {
|
|
@@ -419,6 +623,7 @@ async function verifySellableMcpRuntimeOnce({
|
|
|
419
623
|
let missingTools = [...requiredTools];
|
|
420
624
|
let forbiddenTools = [];
|
|
421
625
|
let createCampaignSmoke = null;
|
|
626
|
+
let connectionOnlyEvergreenContract = { ok: false, issues: [] };
|
|
422
627
|
let error = null;
|
|
423
628
|
|
|
424
629
|
try {
|
|
@@ -432,6 +637,8 @@ async function verifySellableMcpRuntimeOnce({
|
|
|
432
637
|
forbiddenTools = availableTools.filter((tool) =>
|
|
433
638
|
FORBIDDEN_SELLABLE_MCP_TOOLS.includes(tool)
|
|
434
639
|
);
|
|
640
|
+
connectionOnlyEvergreenContract =
|
|
641
|
+
verifyConnectionOnlyEvergreenContract(toolList.tools);
|
|
435
642
|
if (forbiddenTools.length > 0) {
|
|
436
643
|
createCampaignSmoke = {
|
|
437
644
|
ok: false,
|
|
@@ -475,6 +682,7 @@ async function verifySellableMcpRuntimeOnce({
|
|
|
475
682
|
!error &&
|
|
476
683
|
missingTools.length === 0 &&
|
|
477
684
|
forbiddenTools.length === 0 &&
|
|
685
|
+
connectionOnlyEvergreenContract.ok === true &&
|
|
478
686
|
createCampaignSmoke?.ok === true,
|
|
479
687
|
skipped: false,
|
|
480
688
|
command,
|
|
@@ -483,6 +691,7 @@ async function verifySellableMcpRuntimeOnce({
|
|
|
483
691
|
availableTools,
|
|
484
692
|
missingTools,
|
|
485
693
|
forbiddenTools,
|
|
694
|
+
connectionOnlyEvergreenContract,
|
|
486
695
|
createCampaignSmoke,
|
|
487
696
|
stderrTail: stderrLines,
|
|
488
697
|
error: error ? redact(error) : null,
|
package/package.json
CHANGED
|
@@ -721,7 +721,7 @@ Treat host capabilities as concrete functions, not prose conventions:
|
|
|
721
721
|
import and before dispatching Message Drafting only.
|
|
722
722
|
- `launch_message_drafting`: Claude Code uses `Task` with `subagent_type`
|
|
723
723
|
`post-find-leads-message-scout` when listed; Codex uses the returned
|
|
724
|
-
compatibility agent or a generic `gpt-5.
|
|
724
|
+
compatibility agent or a generic `gpt-5.6-sol` / `high` Message Drafting agent.
|
|
725
725
|
|
|
726
726
|
If a required interactive question function or MCP loader is missing, stop and
|
|
727
727
|
explain the Sellable install/reload problem. Source work uses product-native MCP
|
|
@@ -1082,8 +1082,8 @@ updates.
|
|
|
1082
1082
|
In Codex, the filter-choice answer is the campaign-scoped go-ahead to use
|
|
1083
1083
|
this single Message Drafting background agent in step-wise and YOLO modes.
|
|
1084
1084
|
Do not ask a separate question to start it. If the named custom agent is not
|
|
1085
|
-
available, spawn a generic background agent with `model: "gpt-5.
|
|
1086
|
-
`reasoning_effort: "
|
|
1085
|
+
available, spawn a generic background agent with `model: "gpt-5.6-sol"` and
|
|
1086
|
+
`reasoning_effort: "high"` using the same lean campaign/table basis. If no
|
|
1087
1087
|
background-agent tool is callable, start the same full message branch inline
|
|
1088
1088
|
before filter drafting or skip-filter message review and record it as
|
|
1089
1089
|
`statusSource: "parent-thread-fallback"`.
|
|
@@ -134,6 +134,19 @@ run without user input, or similar, run in **automation mode**:
|
|
|
134
134
|
exactly one quality-valid route-proof row when needed, and attach the
|
|
135
135
|
recommended sequence, but it still must not launch campaigns, schedule
|
|
136
136
|
sends, send messages, or spend paid InMail.
|
|
137
|
+
- **Connection-only evergreen completion is optional and non-default.** Use it
|
|
138
|
+
only when the prompt explicitly says connection-only, invite-only,
|
|
139
|
+
connection request only, no DMs, or no follow-ups. Pass the typed option
|
|
140
|
+
`campaignSequenceOptions:{ mode:"connection_only" }` plus an explicit
|
|
141
|
+
`workspaceId` to `setup_evergreen_campaigns`. Omit
|
|
142
|
+
`campaignSequenceOptions` for the standard tier-recommended Premium,
|
|
143
|
+
Sales Nav, Recruiter, and paid InMail behavior.
|
|
144
|
+
Connection-only completion still creates/reuses the same evergreen lanes,
|
|
145
|
+
source rows, and paused/unlaunched review state, but it attaches only the
|
|
146
|
+
canonical invite template and persists `currentStep:"send"` as the paused
|
|
147
|
+
review step. It does not require Message Drafting, generated messages,
|
|
148
|
+
route-proof approval, first DM, InMail, View Profile fallback, follow-up
|
|
149
|
+
branch, launch, scheduling, or sends.
|
|
137
150
|
|
|
138
151
|
If the invoking prompt explicitly asks for interactive message polish or sample
|
|
139
152
|
proof, run in **interactive polish mode** and use the confirmation/sample steps
|
|
@@ -424,7 +437,7 @@ fallback only when app thread tools are unavailable; the receipt must include
|
|
|
424
437
|
`fallbackReason`, or backend verify rejects it.
|
|
425
438
|
When visible Codex app thread tools are unavailable but local Codex CLI is
|
|
426
439
|
available, the accepted durable streaming-worker command shape is:
|
|
427
|
-
`codex -a never -s danger-full-access -c model_reasoning_effort=
|
|
440
|
+
`codex -a never -s danger-full-access -c model_reasoning_effort=high exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> -`.
|
|
428
441
|
The approval, sandbox, and reasoning-effort config flags must come before the
|
|
429
442
|
`exec` subcommand for Codex CLI builds that expose `-a`/`-s`/`-c` only at top
|
|
430
443
|
level. `--skip-git-repo-check` belongs after `exec` because current customer and VPS Codex CLI builds expose it
|
|
@@ -434,26 +447,26 @@ forms fail on current customer CLI installs. Pipe the lane packet prompt on
|
|
|
434
447
|
stdin, require the worker to write `workerDispatch.receiptArtifactHint`, and
|
|
435
448
|
pass exactly one lane packet per worker.
|
|
436
449
|
When launching durable Codex CLI workers from an automation parent, pass an
|
|
437
|
-
explicit supported worker model and explicit `
|
|
450
|
+
explicit supported worker model and explicit `high` reasoning effort instead
|
|
438
451
|
of relying on the Codex CLI defaults. Use the parent runtime model when known,
|
|
439
452
|
for example:
|
|
440
|
-
`codex -a never -s danger-full-access -c model_reasoning_effort=
|
|
453
|
+
`codex -a never -s danger-full-access -c model_reasoning_effort=high exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> -`.
|
|
441
454
|
In Codex CLI, the parent runtime model is visible in the run header as
|
|
442
455
|
`model: <model-name>`. Copy that exact model string into child worker launches
|
|
443
|
-
first. If the parent header says `model: gpt-5.
|
|
444
|
-
`-m gpt-5.
|
|
456
|
+
first. If the parent header says `model: gpt-5.6-sol`, launch workers with
|
|
457
|
+
`-m gpt-5.6-sol` plus `-c model_reasoning_effort=high`; do not invent or probe
|
|
445
458
|
nearby aliases such as `gpt-5.3-codex`, `gpt-5.2`, `gpt-5-codex`,
|
|
446
459
|
`codex-latest`, or `codex-mini-latest` before trying the exact parent model. A
|
|
447
|
-
one-line probe must include the same `-c model_reasoning_effort=
|
|
460
|
+
one-line probe must include the same `-c model_reasoning_effort=high` override
|
|
448
461
|
and count as supported only when it exits 0 and returns the requested output; a
|
|
449
462
|
session header followed by a `not supported` error is rejected, not accepted.
|
|
450
463
|
Do not rely on the Codex CLI default model or default reasoning effort; some
|
|
451
|
-
customer and VPS installs default to unavailable model aliases or to
|
|
452
|
-
|
|
453
|
-
with `high
|
|
454
|
-
`
|
|
464
|
+
customer and VPS installs default to unavailable model aliases or to reasoning
|
|
465
|
+
below `high`. `-m gpt-5.6-sol` alone is not enough. If a child worker reports GPT 5.6-Sol
|
|
466
|
+
with reasoning below `high`, treat that as a launcher bug, relaunch with the explicit
|
|
467
|
+
`high` config before mutation, and do not ask the user to continue through the
|
|
455
468
|
model-quality warning. If the parent cannot identify a supported worker model
|
|
456
|
-
and launch it with `
|
|
469
|
+
and launch it with `high` reasoning, stop with
|
|
457
470
|
`blocked: worker_model_unavailable` before mutation.
|
|
458
471
|
When wrapping multiple local Codex CLI workers in a shell launcher, run the
|
|
459
472
|
wrapper with `/bin/bash -lc` or another explicitly chosen portable shell. Do not
|
|
@@ -466,7 +479,7 @@ Do not embed `<<'WORKER_PROMPT'` heredocs inside a single quoted or double
|
|
|
466
479
|
quoted `/bin/bash -lc '...'` command string; nested quoting is brittle and can
|
|
467
480
|
truncate the first worker before mutation. For multi-worker launchers, write one
|
|
468
481
|
plain prompt file per lane under the current run directory, then start each
|
|
469
|
-
worker with `codex -a never -s danger-full-access -c model_reasoning_effort=
|
|
482
|
+
worker with `codex -a never -s danger-full-access -c model_reasoning_effort=high exec --skip-git-repo-check -m "$WORKER_MODEL" -C "$REPO" -o
|
|
470
483
|
"$worker_final_file" - < "$worker_prompt_file"`. Keep launcher shell variables
|
|
471
484
|
double-quoted and keep the prompt heredoc only in a standalone script/prompt-file
|
|
472
485
|
write step, not inside an already quoted shell argument. If the first launcher
|
|
@@ -572,7 +585,7 @@ launchers, write the same prompt body to `<worker-prompt-file>` and launch the
|
|
|
572
585
|
worker with stdin redirected from that file:
|
|
573
586
|
|
|
574
587
|
```
|
|
575
|
-
codex -a never -s danger-full-access -c model_reasoning_effort=
|
|
588
|
+
codex -a never -s danger-full-access -c model_reasoning_effort=high exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> - <<'WORKER_PROMPT'
|
|
576
589
|
Use $sellable:create-campaign as the governing campaign workflow for this one lane worker.
|
|
577
590
|
Use the evergreen plan/packet below only for lane scope, source metadata,
|
|
578
591
|
postconditions, side-effect caps, and durable receipt proof.
|
|
@@ -619,10 +632,10 @@ Do not launch, start, schedule, send, or use paid InMail.
|
|
|
619
632
|
For filter proof, durable receipt status must be `filterDecisionReceipt.status:"applied"` only; never `completed`, `confirmed`, `done`, or aliases.
|
|
620
633
|
For generated messages, `update_cell` is allowed only for the semantic Approved checkbox. Never use `update_cell` for generated message text/body/sample copy. Bad copy requires `revise_message_template_and_rerun` or brief/template revision plus Generate Message rerun. Any generated-message cell override is `blocked: generated_message_cell_override`.
|
|
621
634
|
If `bootstrap_create_campaign.modelQuality.status === "warn"` because the child
|
|
622
|
-
worker reports GPT 5.
|
|
635
|
+
worker reports GPT 5.6-Sol with reasoning below `high`, that is a parent launcher
|
|
623
636
|
configuration bug, not an operator approval path inside the worker. Stop before
|
|
624
637
|
mutation, tell the parent to relaunch this lane with
|
|
625
|
-
`-c model_reasoning_effort=
|
|
638
|
+
`-c model_reasoning_effort=high`, and do not mark the worker goal complete.
|
|
626
639
|
Complete only this lane. Do not end with narration only. Before your final
|
|
627
640
|
response, run a local file-existence and JSON self-check for
|
|
628
641
|
<receiptArtifactPath>. If the lane succeeded, write the canonical success
|
|
@@ -643,7 +656,7 @@ receipt, or an accepted Post Engagers no-source blocked/no-op receipt.
|
|
|
643
656
|
WORKER_PROMPT
|
|
644
657
|
|
|
645
658
|
# Multi-worker launcher equivalent:
|
|
646
|
-
codex -a never -s danger-full-access -c model_reasoning_effort=
|
|
659
|
+
codex -a never -s danger-full-access -c model_reasoning_effort=high exec --skip-git-repo-check -m <worker-model> -C <repo> -o <worker-final-file> - < <worker-prompt-file>
|
|
647
660
|
```
|
|
648
661
|
|
|
649
662
|
If any placeholder cannot be filled from the current plan, matching
|
|
@@ -720,6 +733,9 @@ not a parent-thread summary. The receipt must include:
|
|
|
720
733
|
creation, preserve that original packet only in a separate `parentLanePacket`
|
|
721
734
|
object; do not leave `setupPlanCall.campaignId:null` or
|
|
722
735
|
`setupPlanCall.tableId:null`.
|
|
736
|
+
If the parent plan used connection-only, the receipt must also include
|
|
737
|
+
`setupPlanCall.campaignSequenceOptions:{ "mode":"connection_only" }` or
|
|
738
|
+
`setupPlanCall.sequencePolicy.mode:"connection_only"`.
|
|
723
739
|
Short form: For create lanes, `setupPlanCall.campaignId` and `setupPlanCall.tableId` must be the actual created campaign/table ids.
|
|
724
740
|
Short form: Do not leave `setupPlanCall.campaignId:null` or `setupPlanCall.tableId:null`.
|
|
725
741
|
- `createCampaignWorkflowReceipt`: proof the worker loaded the actual installed
|
|
@@ -810,22 +826,40 @@ not a parent-thread summary. The receipt must include:
|
|
|
810
826
|
them into canonical `promptLoadedToHasMoreFalse`, `requiredAssetsLoaded`,
|
|
811
827
|
`validationLoaded`, `reviewBatchRowHash`, and
|
|
812
828
|
`messageDraftRecommendation`.
|
|
829
|
+
Connection-only lanes are the exception: do not include
|
|
830
|
+
`messageDraftingReceipt` or run generated-message prep unless the operator
|
|
831
|
+
separately asked for message copy. The parent verifier expects no message
|
|
832
|
+
proof for connection-only lanes.
|
|
813
833
|
- `reviewBatchReceipt`: review-batch row ids/hash, generated row count,
|
|
814
834
|
quality-valid route-proof row id when approved, and proof that no broad
|
|
815
835
|
approve-all occurred.
|
|
836
|
+
Connection-only lanes are the exception: do not approve a route-proof row and
|
|
837
|
+
do not include a required review-batch receipt.
|
|
816
838
|
- `sequenceReceipt`: exact current workflowTableId, recommended non-paid
|
|
817
839
|
sequence attach/precheck result, and readback showing `hasSequence:true` when
|
|
818
840
|
completion is claimed. If the tool output uses
|
|
819
841
|
`attachRecommendedSequenceResult.actionTypes` or
|
|
820
842
|
`nonPaidRecommendedSequence`, copy them to canonical `actionTypes` and
|
|
821
843
|
`nonPaid`.
|
|
844
|
+
For connection-only lanes, do not call `attach_recommended_sequence`. Attach
|
|
845
|
+
with `attach_sequence({ tableId, templateRef:"connection_only", currentStep:"send" })`, then
|
|
846
|
+
include exact current-template proof:
|
|
847
|
+
`sequenceReceipt.hasSequence:true`,
|
|
848
|
+
`sequenceReceipt.actionTypes:["send_invite"]`, and
|
|
849
|
+
`sequenceReceipt.nonPaid:true`. Receipts that only say
|
|
850
|
+
`tool:"attach_recommended_sequence"` or include `send_dm`,
|
|
851
|
+
`send_inmail_open`, `send_inmail_closed`, or `view_profile` are failing
|
|
852
|
+
connection-only receipts.
|
|
822
853
|
- final paused-send proof: if the current campaign table is `DRAFT` after the
|
|
823
854
|
sequence is attached, call the product `pause_campaign({ campaignId })`
|
|
824
855
|
endpoint/tool to put the unlaunched campaign into `PAUSED` review state, then
|
|
825
856
|
reread the campaign/table. Do not raw-write `campaignStatus`, do not start or
|
|
826
857
|
launch, and do not schedule/send. Completion requires reread proof of
|
|
827
|
-
`currentStep:"send"` and `campaignStatus:"PAUSED"
|
|
828
|
-
|
|
858
|
+
`currentStep:"send"` and `campaignStatus:"PAUSED"` for standard and
|
|
859
|
+
connection-only customer-visible lanes. `send` is the product's paused
|
|
860
|
+
review step; do not use unsupported aliases such as `review` as final proof.
|
|
861
|
+
If the raw output nests this in `finalCampaignRead` or `finalTableRead`, copy
|
|
862
|
+
it to canonical
|
|
829
863
|
`finalPausedSendProof.currentStep` and
|
|
830
864
|
`finalPausedSendProof.campaignStatus`.
|
|
831
865
|
- `verifyCall`: the exact `setup_evergreen_campaigns({ mode:"verify",
|
|
@@ -1088,9 +1122,14 @@ plain row generation. The lane worker must inline the same
|
|
|
1088
1122
|
approvedGeneratedMessageCount exactly 1. Do not report completion with 2+
|
|
1089
1123
|
approved rows.
|
|
1090
1124
|
Approval shorthand: Do not report completion with 2+ approved rows.
|
|
1091
|
-
8.
|
|
1092
|
-
|
|
1093
|
-
|
|
1125
|
+
8. Standard mode: continue to
|
|
1126
|
+
`attach_recommended_sequence({ campaignId, currentStep:"send" })` and, if
|
|
1127
|
+
the campaign is still `DRAFT`, `pause_campaign({ campaignId })`. Reread the
|
|
1128
|
+
campaign/table before claiming completion.
|
|
1129
|
+
Connection-only mode: skip Message Drafting and route-proof approval, call
|
|
1130
|
+
`attach_sequence({ tableId, templateRef:"connection_only", currentStep:"send" })`, prove
|
|
1131
|
+
`sequenceReceipt.actionTypes:["send_invite"]`, and pause/reread without
|
|
1132
|
+
launching or sending.
|
|
1094
1133
|
|
|
1095
1134
|
That packaged worker path must return `messageDraftingReceipt.statusSource:
|
|
1096
1135
|
"packaged-generate-messages-worker"`. It is accepted only when the receipt
|
|
@@ -1515,11 +1554,14 @@ Message, and verify current-revision sample messages before final completion.
|
|
|
1515
1554
|
- DM lanes: add a `Delivery format:` line — either `multiline (each paragraph sends as its own DM message)` or `single message`. When multiline, the template's blank-line paragraphs ARE the message boundaries — write each one as a standalone typed message.
|
|
1516
1555
|
- **InMail lanes can never be multiline**: an InMail is one message and the recipient must reply before anything else can be sent. InMail-bound templates must read as one cohesive message — declare `Delivery format: single message (InMail — no follow-up until reply)` and never structure the copy to depend on multi-message pacing.
|
|
1517
1556
|
|
|
1518
|
-
-
|
|
1557
|
+
- In standard mode, the sequence is auto-selected by sender tier; do not hand-author sequence
|
|
1519
1558
|
templates here. Sales Nav/Recruiter senders may receive the unified Sales
|
|
1520
1559
|
Nav cascade through `attach_recommended_sequence`; attaching it does not
|
|
1521
1560
|
spend paid InMail credits by itself. Do not substitute the manual Paid
|
|
1522
1561
|
InMail Campaign template.
|
|
1562
|
+
For explicit connection-only evergreen lanes only, use the backend-owned
|
|
1563
|
+
`attach_sequence({ tableId, templateRef:"connection_only", currentStep:"send" })` path and do
|
|
1564
|
+
not call `attach_recommended_sequence`.
|
|
1523
1565
|
3. **Customer-Visible Completion Contract**: a named evergreen lane that appears
|
|
1524
1566
|
as a campaign card or campaign-backed table is not done when the shell exists.
|
|
1525
1567
|
It is done only when the customer can open the campaign and land on final
|
|
@@ -1543,7 +1585,7 @@ Message, and verify current-revision sample messages before final completion.
|
|
|
1543
1585
|
evergreen setup. Do not leave customer-visible campaigns at
|
|
1544
1586
|
`filter-choice`, `filter-rules`, or `apply-icp-rubric` and report success.
|
|
1545
1587
|
Do not proceed to Message Drafting until saved filters are applied.
|
|
1546
|
-
- Message Drafting has run from the current campaign/table basis, using the
|
|
1588
|
+
- In standard mode, Message Drafting has run from the current campaign/table basis, using the
|
|
1547
1589
|
create-campaign message prompt/assets and validation gate. Updating
|
|
1548
1590
|
`currentStep:"messages"` is not proof. Parent-thread handwritten copy is
|
|
1549
1591
|
not a substitute. The proof receipt must show
|
|
@@ -1584,6 +1626,9 @@ Message, and verify current-revision sample messages before final completion.
|
|
|
1584
1626
|
Fallback samples must still reject source/conversation hedges such as
|
|
1585
1627
|
`"hope this is relevant"`, `"might be interested"`, or `"saw you in a few
|
|
1586
1628
|
conversations"`.
|
|
1629
|
+
For explicit connection-only lanes, this whole Message Drafting and sample
|
|
1630
|
+
proof block is not required and must not be faked with parent-written
|
|
1631
|
+
messages.
|
|
1587
1632
|
- The first review batch exists and at least 3 review rows have generated
|
|
1588
1633
|
messages from the approved brief. If fewer than 3 usable rows exist, report
|
|
1589
1634
|
the actual count and why.
|
|
@@ -1596,7 +1641,7 @@ Message, and verify current-revision sample messages before final completion.
|
|
|
1596
1641
|
completion, approve exactly one quality-valid generated row. If one or more
|
|
1597
1642
|
rows are already approved, do not add more approvals during evergreen
|
|
1598
1643
|
completion. Never broad approve all rows.
|
|
1599
|
-
-
|
|
1644
|
+
- In standard mode, the recommended tier-aware sequence is attached to the current campaign
|
|
1600
1645
|
table, and the watched campaign is on Send. Use
|
|
1601
1646
|
`attach_recommended_sequence({ campaignId, currentStep:"send" })` when a
|
|
1602
1647
|
safe attach is needed. After `confirm_lead_list` or any source-list copy,
|
|
@@ -1611,6 +1656,10 @@ Message, and verify current-revision sample messages before final completion.
|
|
|
1611
1656
|
manual Paid InMail Campaign, and never attach/replace sequence outside the
|
|
1612
1657
|
current table unless the current lane packet explicitly allowed sequence
|
|
1613
1658
|
repair.
|
|
1659
|
+
For explicit connection-only lanes, the current campaign table must have
|
|
1660
|
+
exactly the canonical invite-only sequence:
|
|
1661
|
+
`sequenceReceipt.actionTypes:["send_invite"]`. Any DM, InMail, or View
|
|
1662
|
+
Profile action means the lane is not complete.
|
|
1614
1663
|
- If the current campaign table is still `DRAFT` after sequence/readiness
|
|
1615
1664
|
proof, call `pause_campaign({ campaignId })` and reread. `pause_campaign`
|
|
1616
1665
|
is the product-native review-state transition; it is not a launch and does
|
|
@@ -62,6 +62,11 @@ for lease expiry; never guess a fence.
|
|
|
62
62
|
The default `intent:"auto"` inspects `managed_waterfall`,
|
|
63
63
|
`dashboard_evergreen`, and `active_campaign` lane sources. Report the lane
|
|
64
64
|
source and lane chain as proof for every selected sender.
|
|
65
|
+
Connection-only evergreen lanes are invite-only refill targets. When the packet
|
|
66
|
+
or campaign proof shows exactly `["send_invite"]`, report and execute only
|
|
67
|
+
`selectedLane:"send_invite"` work; do not infer DM, InMail, Sales Nav cascade,
|
|
68
|
+
paid-credit refresh, message generation, follow-up, sequence mutation,
|
|
69
|
+
launch/start beyond packet authority, scheduler writes, or direct sends.
|
|
65
70
|
|
|
66
71
|
If membership blocks a workspace read, report the structured
|
|
67
72
|
`workspace_access` blocker instead of retrying auth or switching workspaces.
|
|
@@ -196,6 +196,11 @@ rather than asking which campaign class to fill. If a stale target plan selects
|
|
|
196
196
|
planner before mutation.
|
|
197
197
|
Short form: trust the target plan's inferred lane when it is a connection invite,
|
|
198
198
|
paid-InMail refill lane, or unified Sales Nav cascade.
|
|
199
|
+
Connection-only evergreen campaigns with exact `["send_invite"]` sequence proof
|
|
200
|
+
are plain invite capacity: treat them as `selectedLane:"send_invite"` only. Do
|
|
201
|
+
not infer DM, InMail, Sales Nav cascade, paid-credit refresh, message
|
|
202
|
+
generation, follow-up, sequence mutation, launch/start, scheduling override, or
|
|
203
|
+
direct-send work from a connection-only lane.
|
|
199
204
|
|
|
200
205
|
Structured planner packet:
|
|
201
206
|
|