@sellable/install 0.1.76 → 0.1.78
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.
|
@@ -20,11 +20,11 @@ Required first steps:
|
|
|
20
20
|
1. Read the three required inputs.
|
|
21
21
|
2. Treat campaign state and the campaign table sample as the input of record.
|
|
22
22
|
Disk files are context/debug aids, not durable state.
|
|
23
|
-
3. Use the embedded Message Review
|
|
24
|
-
long-form `generate-messages` subskill in
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
3. Use the embedded Message Review Safety Gate below. Do not load the full
|
|
24
|
+
long-form `generate-messages` subskill in this `create-campaign-v2` path. If
|
|
25
|
+
a needed rule is missing or the draft fails quality gates, return
|
|
26
|
+
`revise-messaging` with the exact failure instead of pulling the long prompt
|
|
27
|
+
into this worker.
|
|
28
28
|
|
|
29
29
|
Owned outputs:
|
|
30
30
|
|
|
@@ -46,8 +46,8 @@ Do not write or modify:
|
|
|
46
46
|
|
|
47
47
|
Process:
|
|
48
48
|
|
|
49
|
-
1. Run the embedded
|
|
50
|
-
lead-review source decision, and `lead-sample.json`.
|
|
49
|
+
1. Run the embedded message-review safety-gate workflow in dry mode from the
|
|
50
|
+
approved brief, lead-review source decision, and `lead-sample.json`.
|
|
51
51
|
2. Use `lead-sample.json` as the only lead sample source. Do not fetch new
|
|
52
52
|
prospects or invent richer row signals.
|
|
53
53
|
3. Build proof inventory, token fill rules, token adherence, angle drafts,
|
|
@@ -69,7 +69,8 @@ Process:
|
|
|
69
69
|
Return a concise final status with:
|
|
70
70
|
|
|
71
71
|
- artifacts written
|
|
72
|
-
- whether embedded
|
|
72
|
+
- whether the embedded message-review safety-gate rules passed or returned
|
|
73
|
+
`revise-messaging`
|
|
73
74
|
- lead sample basis used
|
|
74
75
|
- proposed template and one sample message
|
|
75
76
|
- selected winner summary
|
|
@@ -78,12 +79,12 @@ Return a concise final status with:
|
|
|
78
79
|
Quality bar:
|
|
79
80
|
|
|
80
81
|
- Do not synthesize a lightweight message from general knowledge. The artifact
|
|
81
|
-
must prove the embedded
|
|
82
|
+
must prove the embedded message-review safety-gate workflow ran.
|
|
82
83
|
- Message generation can start before `lead-filter.md`, but message review
|
|
83
84
|
cannot start until the parent verifies the selected basis rows still pass the
|
|
84
85
|
final filter.
|
|
85
86
|
|
|
86
|
-
## Embedded Message Review
|
|
87
|
+
## Embedded Message Review Safety Gate
|
|
87
88
|
|
|
88
89
|
Use this campaign-launch subset to produce a truthful first-send message,
|
|
89
90
|
rendered token examples, and a decision without loading the full long-form
|
package/bin/sellable-install.mjs
CHANGED
|
@@ -843,15 +843,21 @@ updates.
|
|
|
843
843
|
4. For message generation, use the \`post-find-leads-message-scout\` agent when
|
|
844
844
|
available; its prompt carries the campaign-launch message rules. In the
|
|
845
845
|
parent-thread fallback, load
|
|
846
|
-
\`mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-
|
|
846
|
+
\`mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-safety-gate.md" })\`.
|
|
847
|
+
Do not load the full long-form \`generate-messages\` subskill in this
|
|
848
|
+
create-campaign path; if the safety gate cannot safely approve the draft, route
|
|
849
|
+
to revise messaging with the concrete failure.
|
|
847
850
|
Do not synthesize \`message-validation.md\` from the brief, lead review, or
|
|
848
851
|
general knowledge.
|
|
849
|
-
5.
|
|
850
|
-
|
|
851
|
-
the
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
\`
|
|
852
|
+
5. Create the campaign shell early with the v1 brief so the user can open the
|
|
853
|
+
watch link and see useful setup state immediately. Import only the first
|
|
854
|
+
bounded review batch after the source is attached to the campaign; do not
|
|
855
|
+
queue workflow cells, attach a sequence, or start until
|
|
856
|
+
\`message-validation.md\` proves the message-review safety-gate workflow ran,
|
|
857
|
+
\`message-review.md\` approves the template, rubrics are saved, and the
|
|
858
|
+
approved message set is synced into the campaign brief.
|
|
859
|
+
6. Keep \`selectedLeadListId\` as the source list and \`workflowTableId\` as the
|
|
860
|
+
campaign table. Do not use disk files as the post-mint source of truth.
|
|
855
861
|
7. Do not ask the user to run another command.
|
|
856
862
|
|
|
857
863
|
## Fallback
|
|
@@ -1121,15 +1127,24 @@ function agentTemplateRoot() {
|
|
|
1121
1127
|
|
|
1122
1128
|
function loadCanonicalAgents() {
|
|
1123
1129
|
const root = agentTemplateRoot();
|
|
1124
|
-
const registry = JSON.parse(
|
|
1130
|
+
const registry = JSON.parse(
|
|
1131
|
+
readFileSync(join(root, "registry.json"), "utf8")
|
|
1132
|
+
);
|
|
1125
1133
|
if (!Array.isArray(registry.agents)) {
|
|
1126
1134
|
throw new Error("Sellable agent registry is missing agents array.");
|
|
1127
1135
|
}
|
|
1128
1136
|
|
|
1129
1137
|
return registry.agents.map((agent) => {
|
|
1130
1138
|
const promptPath = join(root, agent.promptFile || "");
|
|
1131
|
-
if (
|
|
1132
|
-
|
|
1139
|
+
if (
|
|
1140
|
+
!agent.id ||
|
|
1141
|
+
!agent.name ||
|
|
1142
|
+
!agent.promptFile ||
|
|
1143
|
+
!existsSync(promptPath)
|
|
1144
|
+
) {
|
|
1145
|
+
throw new Error(
|
|
1146
|
+
`Invalid Sellable agent registry entry: ${agent.id || "unknown"}`
|
|
1147
|
+
);
|
|
1133
1148
|
}
|
|
1134
1149
|
if (agent.codex?.name && agent.codex.name !== agent.name) {
|
|
1135
1150
|
throw new Error(
|
|
@@ -1165,6 +1180,15 @@ function legacyClaudeCustomAgents() {
|
|
|
1165
1180
|
return loadCanonicalAgents().flatMap((agent) => agent.legacy?.claude || []);
|
|
1166
1181
|
}
|
|
1167
1182
|
|
|
1183
|
+
function legacyClaudeCommands() {
|
|
1184
|
+
return [
|
|
1185
|
+
{
|
|
1186
|
+
name: "sellable-create-campaign",
|
|
1187
|
+
filename: join("sellable", "create-campaign.md"),
|
|
1188
|
+
},
|
|
1189
|
+
];
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1168
1192
|
function tomlArray(values) {
|
|
1169
1193
|
return `[${values.map((value) => quoteToml(value)).join(", ")}]`;
|
|
1170
1194
|
}
|
|
@@ -1240,7 +1264,9 @@ function writeCodexCustomAgents(home, opts) {
|
|
|
1240
1264
|
}
|
|
1241
1265
|
for (const agent of legacyCodexCustomAgents()) {
|
|
1242
1266
|
const legacyPath = join(home, "agents", agent.filename);
|
|
1243
|
-
logVerbose(
|
|
1267
|
+
logVerbose(
|
|
1268
|
+
`${C.grey}Removing legacy Codex scout agent ${legacyPath}${C.reset}`
|
|
1269
|
+
);
|
|
1244
1270
|
if (!opts.dryRun) rmSync(legacyPath, { force: true });
|
|
1245
1271
|
}
|
|
1246
1272
|
}
|
|
@@ -1256,9 +1282,22 @@ function writeClaudeCustomAgents(opts) {
|
|
|
1256
1282
|
}
|
|
1257
1283
|
for (const agent of legacyClaudeCustomAgents()) {
|
|
1258
1284
|
const legacyPath = join(home, "agents", agent.filename);
|
|
1259
|
-
logVerbose(
|
|
1285
|
+
logVerbose(
|
|
1286
|
+
`${C.grey}Removing legacy Claude scout agent ${legacyPath}${C.reset}`
|
|
1287
|
+
);
|
|
1260
1288
|
if (!opts.dryRun) rmSync(legacyPath, { force: true });
|
|
1261
1289
|
}
|
|
1290
|
+
removeLegacyClaudeCommands(home, opts);
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
function removeLegacyClaudeCommands(home, opts) {
|
|
1294
|
+
for (const command of legacyClaudeCommands()) {
|
|
1295
|
+
const commandPath = join(home, "commands", command.filename);
|
|
1296
|
+
logVerbose(
|
|
1297
|
+
`${C.grey}Removing legacy Claude command ${commandPath}${C.reset}`
|
|
1298
|
+
);
|
|
1299
|
+
if (!opts.dryRun) rmSync(commandPath, { force: true });
|
|
1300
|
+
}
|
|
1262
1301
|
}
|
|
1263
1302
|
|
|
1264
1303
|
function installCodexDesktopPlugin(opts) {
|
|
@@ -1396,8 +1435,12 @@ config_file = ${quoteToml(join(home, "agents", agent.filename))}`
|
|
|
1396
1435
|
logVerbose(
|
|
1397
1436
|
`${C.grey}+ enable [features].default_mode_request_user_input in ${configPath}${C.reset}`
|
|
1398
1437
|
);
|
|
1399
|
-
logVerbose(
|
|
1400
|
-
|
|
1438
|
+
logVerbose(
|
|
1439
|
+
`${C.grey}+ write Codex custom agents in ${home}/agents${C.reset}`
|
|
1440
|
+
);
|
|
1441
|
+
logVerbose(
|
|
1442
|
+
`${C.grey}+ register Codex custom agents in ${configPath}${C.reset}`
|
|
1443
|
+
);
|
|
1401
1444
|
}
|
|
1402
1445
|
|
|
1403
1446
|
return {
|
|
@@ -1607,6 +1650,23 @@ function verify(opts) {
|
|
|
1607
1650
|
? "Claude scout MCP tool allowlists present"
|
|
1608
1651
|
: "Claude scout MCP tool allowlists missing",
|
|
1609
1652
|
});
|
|
1653
|
+
const legacyClaudePaths = [
|
|
1654
|
+
...legacyClaudeCustomAgents().map((agent) =>
|
|
1655
|
+
join(claudeHome(), "agents", agent.filename)
|
|
1656
|
+
),
|
|
1657
|
+
...legacyClaudeCommands().map((command) =>
|
|
1658
|
+
join(claudeHome(), "commands", command.filename)
|
|
1659
|
+
),
|
|
1660
|
+
];
|
|
1661
|
+
const hasNoLegacyClaudeArtifacts = legacyClaudePaths.every(
|
|
1662
|
+
(artifactPath) => !existsSync(artifactPath)
|
|
1663
|
+
);
|
|
1664
|
+
checks.push({
|
|
1665
|
+
ok: hasNoLegacyClaudeArtifacts,
|
|
1666
|
+
label: hasNoLegacyClaudeArtifacts
|
|
1667
|
+
? "Legacy Claude Sellable host artifacts cleaned"
|
|
1668
|
+
: "Legacy Claude Sellable host artifacts still present",
|
|
1669
|
+
});
|
|
1610
1670
|
}
|
|
1611
1671
|
if (opts.host === "codex" || opts.host === "all") {
|
|
1612
1672
|
checks.push({
|
|
@@ -1671,6 +1731,19 @@ function verify(opts) {
|
|
|
1671
1731
|
? "Codex custom scout agents registered"
|
|
1672
1732
|
: "Codex custom scout agents unregistered",
|
|
1673
1733
|
});
|
|
1734
|
+
const hasNoLegacyCodexAgents = legacyCodexCustomAgents().every((agent) => {
|
|
1735
|
+
const agentPath = join(codexHome(), "agents", agent.filename);
|
|
1736
|
+
return (
|
|
1737
|
+
!existsSync(agentPath) &&
|
|
1738
|
+
!configContent.includes(`[agents.${agent.name}]`)
|
|
1739
|
+
);
|
|
1740
|
+
});
|
|
1741
|
+
checks.push({
|
|
1742
|
+
ok: hasNoLegacyCodexAgents,
|
|
1743
|
+
label: hasNoLegacyCodexAgents
|
|
1744
|
+
? "Legacy Codex custom scout agents cleaned"
|
|
1745
|
+
: "Legacy Codex custom scout agents still present",
|
|
1746
|
+
});
|
|
1674
1747
|
const hasFlag = configContent.includes(
|
|
1675
1748
|
"default_mode_request_user_input = true"
|
|
1676
1749
|
);
|
|
@@ -1899,7 +1972,10 @@ function runUninstall() {
|
|
|
1899
1972
|
after = removeTomlSection(after, "marketplaces.sellable");
|
|
1900
1973
|
after = removeTomlSection(after, 'plugins."sellable@sellable"');
|
|
1901
1974
|
after = removeTomlSection(after, 'plugins."sellable@sellable-local"');
|
|
1902
|
-
for (const agent of [
|
|
1975
|
+
for (const agent of [
|
|
1976
|
+
...codexCustomAgents(),
|
|
1977
|
+
...legacyCodexCustomAgents(),
|
|
1978
|
+
]) {
|
|
1903
1979
|
after = removeTomlSection(after, `agents.${agent.name}`);
|
|
1904
1980
|
}
|
|
1905
1981
|
// Collapse 3+ blank lines that the removals may leave behind.
|
|
@@ -1949,7 +2025,10 @@ function runUninstall() {
|
|
|
1949
2025
|
skipped.push(`Claude Code CLI not found`);
|
|
1950
2026
|
}
|
|
1951
2027
|
|
|
1952
|
-
for (const agent of [
|
|
2028
|
+
for (const agent of [
|
|
2029
|
+
...claudeCustomAgents(),
|
|
2030
|
+
...legacyClaudeCustomAgents(),
|
|
2031
|
+
]) {
|
|
1953
2032
|
const agentPath = join(claudeHome(), "agents", agent.filename);
|
|
1954
2033
|
if (!existsSync(agentPath)) continue;
|
|
1955
2034
|
try {
|
|
@@ -1961,6 +2040,18 @@ function runUninstall() {
|
|
|
1961
2040
|
);
|
|
1962
2041
|
}
|
|
1963
2042
|
}
|
|
2043
|
+
for (const command of legacyClaudeCommands()) {
|
|
2044
|
+
const commandPath = join(claudeHome(), "commands", command.filename);
|
|
2045
|
+
if (!existsSync(commandPath)) continue;
|
|
2046
|
+
try {
|
|
2047
|
+
rmSync(commandPath, { force: true });
|
|
2048
|
+
removed.push(`${commandPath}`);
|
|
2049
|
+
} catch (err) {
|
|
2050
|
+
console.log(
|
|
2051
|
+
` ${C.yellow}!${C.reset} Could not remove ${commandPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
1964
2055
|
|
|
1965
2056
|
// 3) Surgical removal of Sellable-installed artifacts inside ~/.sellable/
|
|
1966
2057
|
const sellableDir = join(homedir(), ".sellable");
|
package/package.json
CHANGED
|
@@ -490,14 +490,17 @@ updates.
|
|
|
490
490
|
4. For message generation, use the `post-find-leads-message-scout` agent when
|
|
491
491
|
available; its prompt carries the campaign-launch message rules. In the
|
|
492
492
|
parent-thread fallback, load
|
|
493
|
-
`mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-
|
|
493
|
+
`mcp__sellable__get_subskill_asset({ subskillName: "create-campaign-v2", assetPath: "references/message-review-safety-gate.md" })`.
|
|
494
|
+
Do not load the full long-form `generate-messages` subskill in this
|
|
495
|
+
create-campaign path; if the safety gate cannot safely approve the draft,
|
|
496
|
+
route to revise messaging with the concrete failure.
|
|
494
497
|
Do not synthesize `message-validation.md` from the brief, lead review, or
|
|
495
498
|
general knowledge.
|
|
496
499
|
5. Create the campaign shell early with the v1 brief so the user can open the
|
|
497
500
|
watch link and see useful setup state immediately. Import only the first
|
|
498
501
|
bounded review batch after the source is attached to the campaign; do not
|
|
499
502
|
queue workflow cells, attach a sequence, or start until
|
|
500
|
-
`message-validation.md` proves the
|
|
503
|
+
`message-validation.md` proves the message-review safety-gate workflow ran,
|
|
501
504
|
`message-review.md` approves the template, rubrics are saved, and the
|
|
502
505
|
approved message set is synced into the campaign brief.
|
|
503
506
|
6. Keep `selectedLeadListId` as the source list and `workflowTableId` as the
|