@sellable/install 0.1.77 → 0.1.79

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.
@@ -601,12 +601,11 @@ data, compare sources by source volume, sampled ICP fit, activity/warmth
601
601
  signals, cleanup risk, and confidence basis. If a user asks for a forecast,
602
602
  label it explicitly as not estimated from this run.
603
603
 
604
- Every approval gate must include artifact access after the readable inline
605
- content. Show an \`Open artifacts:\` line with clickable markdown links using
606
- absolute paths when the host supports them, plus the plain path for CLI users.
607
- Do this for brief approval, lead-source approval/review, message review, and the
608
- final approval packet. The links are for deeper inspection; never use them as a
609
- substitute for showing the content in chat.
604
+ Every approval gate must include live campaign access after the readable inline
605
+ content. Show a \`Watch link:\` line once the campaign shell exists. In normal
606
+ customer runs, do not show local draft filenames or filesystem paths unless the
607
+ user asks for debug artifacts. The link is for deeper inspection; never use it
608
+ as a substitute for showing the content in chat.
610
609
 
611
610
  Never mention MCP namespaces, prompt chunking, plugin cache paths, missing
612
611
  linked skill versions, runbooks, or local skill files in normal customer-facing
@@ -960,10 +959,10 @@ approval should show who we are targeting, why they should care, the offer/CTA,
960
959
  proof, lead source hypothesis, message angle, risks/assumptions, and what
961
960
  happens after approval.
962
961
 
963
- Every approval should also give the user a way to inspect the source artifact.
964
- After the readable inline content, include an \`Open artifacts:\` line with links
965
- or plain paths to the files behind the decision. The artifact links are a backup
966
- for inspection, not a replacement for showing the content in chat.
962
+ Every approval should also give the user a way to inspect the live campaign.
963
+ After the readable inline content, include a \`Watch link:\` line when a
964
+ campaign shell exists. Local artifacts are optional debug/UAT diagnostics only;
965
+ do not surface file paths or local draft filenames in normal customer runs.
967
966
 
968
967
  This applies especially to message approvals. Never ask someone to approve a
969
968
  message they cannot see. Show the subject, tokenized template, a filled sample
@@ -1127,15 +1126,24 @@ function agentTemplateRoot() {
1127
1126
 
1128
1127
  function loadCanonicalAgents() {
1129
1128
  const root = agentTemplateRoot();
1130
- const registry = JSON.parse(readFileSync(join(root, "registry.json"), "utf8"));
1129
+ const registry = JSON.parse(
1130
+ readFileSync(join(root, "registry.json"), "utf8")
1131
+ );
1131
1132
  if (!Array.isArray(registry.agents)) {
1132
1133
  throw new Error("Sellable agent registry is missing agents array.");
1133
1134
  }
1134
1135
 
1135
1136
  return registry.agents.map((agent) => {
1136
1137
  const promptPath = join(root, agent.promptFile || "");
1137
- if (!agent.id || !agent.name || !agent.promptFile || !existsSync(promptPath)) {
1138
- throw new Error(`Invalid Sellable agent registry entry: ${agent.id || "unknown"}`);
1138
+ if (
1139
+ !agent.id ||
1140
+ !agent.name ||
1141
+ !agent.promptFile ||
1142
+ !existsSync(promptPath)
1143
+ ) {
1144
+ throw new Error(
1145
+ `Invalid Sellable agent registry entry: ${agent.id || "unknown"}`
1146
+ );
1139
1147
  }
1140
1148
  if (agent.codex?.name && agent.codex.name !== agent.name) {
1141
1149
  throw new Error(
@@ -1171,6 +1179,15 @@ function legacyClaudeCustomAgents() {
1171
1179
  return loadCanonicalAgents().flatMap((agent) => agent.legacy?.claude || []);
1172
1180
  }
1173
1181
 
1182
+ function legacyClaudeCommands() {
1183
+ return [
1184
+ {
1185
+ name: "sellable-create-campaign",
1186
+ filename: join("sellable", "create-campaign.md"),
1187
+ },
1188
+ ];
1189
+ }
1190
+
1174
1191
  function tomlArray(values) {
1175
1192
  return `[${values.map((value) => quoteToml(value)).join(", ")}]`;
1176
1193
  }
@@ -1246,7 +1263,9 @@ function writeCodexCustomAgents(home, opts) {
1246
1263
  }
1247
1264
  for (const agent of legacyCodexCustomAgents()) {
1248
1265
  const legacyPath = join(home, "agents", agent.filename);
1249
- logVerbose(`${C.grey}Removing legacy Codex scout agent ${legacyPath}${C.reset}`);
1266
+ logVerbose(
1267
+ `${C.grey}Removing legacy Codex scout agent ${legacyPath}${C.reset}`
1268
+ );
1250
1269
  if (!opts.dryRun) rmSync(legacyPath, { force: true });
1251
1270
  }
1252
1271
  }
@@ -1262,9 +1281,22 @@ function writeClaudeCustomAgents(opts) {
1262
1281
  }
1263
1282
  for (const agent of legacyClaudeCustomAgents()) {
1264
1283
  const legacyPath = join(home, "agents", agent.filename);
1265
- logVerbose(`${C.grey}Removing legacy Claude scout agent ${legacyPath}${C.reset}`);
1284
+ logVerbose(
1285
+ `${C.grey}Removing legacy Claude scout agent ${legacyPath}${C.reset}`
1286
+ );
1266
1287
  if (!opts.dryRun) rmSync(legacyPath, { force: true });
1267
1288
  }
1289
+ removeLegacyClaudeCommands(home, opts);
1290
+ }
1291
+
1292
+ function removeLegacyClaudeCommands(home, opts) {
1293
+ for (const command of legacyClaudeCommands()) {
1294
+ const commandPath = join(home, "commands", command.filename);
1295
+ logVerbose(
1296
+ `${C.grey}Removing legacy Claude command ${commandPath}${C.reset}`
1297
+ );
1298
+ if (!opts.dryRun) rmSync(commandPath, { force: true });
1299
+ }
1268
1300
  }
1269
1301
 
1270
1302
  function installCodexDesktopPlugin(opts) {
@@ -1402,8 +1434,12 @@ config_file = ${quoteToml(join(home, "agents", agent.filename))}`
1402
1434
  logVerbose(
1403
1435
  `${C.grey}+ enable [features].default_mode_request_user_input in ${configPath}${C.reset}`
1404
1436
  );
1405
- logVerbose(`${C.grey}+ write Codex custom agents in ${home}/agents${C.reset}`);
1406
- logVerbose(`${C.grey}+ register Codex custom agents in ${configPath}${C.reset}`);
1437
+ logVerbose(
1438
+ `${C.grey}+ write Codex custom agents in ${home}/agents${C.reset}`
1439
+ );
1440
+ logVerbose(
1441
+ `${C.grey}+ register Codex custom agents in ${configPath}${C.reset}`
1442
+ );
1407
1443
  }
1408
1444
 
1409
1445
  return {
@@ -1613,6 +1649,23 @@ function verify(opts) {
1613
1649
  ? "Claude scout MCP tool allowlists present"
1614
1650
  : "Claude scout MCP tool allowlists missing",
1615
1651
  });
1652
+ const legacyClaudePaths = [
1653
+ ...legacyClaudeCustomAgents().map((agent) =>
1654
+ join(claudeHome(), "agents", agent.filename)
1655
+ ),
1656
+ ...legacyClaudeCommands().map((command) =>
1657
+ join(claudeHome(), "commands", command.filename)
1658
+ ),
1659
+ ];
1660
+ const hasNoLegacyClaudeArtifacts = legacyClaudePaths.every(
1661
+ (artifactPath) => !existsSync(artifactPath)
1662
+ );
1663
+ checks.push({
1664
+ ok: hasNoLegacyClaudeArtifacts,
1665
+ label: hasNoLegacyClaudeArtifacts
1666
+ ? "Legacy Claude Sellable host artifacts cleaned"
1667
+ : "Legacy Claude Sellable host artifacts still present",
1668
+ });
1616
1669
  }
1617
1670
  if (opts.host === "codex" || opts.host === "all") {
1618
1671
  checks.push({
@@ -1677,6 +1730,19 @@ function verify(opts) {
1677
1730
  ? "Codex custom scout agents registered"
1678
1731
  : "Codex custom scout agents unregistered",
1679
1732
  });
1733
+ const hasNoLegacyCodexAgents = legacyCodexCustomAgents().every((agent) => {
1734
+ const agentPath = join(codexHome(), "agents", agent.filename);
1735
+ return (
1736
+ !existsSync(agentPath) &&
1737
+ !configContent.includes(`[agents.${agent.name}]`)
1738
+ );
1739
+ });
1740
+ checks.push({
1741
+ ok: hasNoLegacyCodexAgents,
1742
+ label: hasNoLegacyCodexAgents
1743
+ ? "Legacy Codex custom scout agents cleaned"
1744
+ : "Legacy Codex custom scout agents still present",
1745
+ });
1680
1746
  const hasFlag = configContent.includes(
1681
1747
  "default_mode_request_user_input = true"
1682
1748
  );
@@ -1905,7 +1971,10 @@ function runUninstall() {
1905
1971
  after = removeTomlSection(after, "marketplaces.sellable");
1906
1972
  after = removeTomlSection(after, 'plugins."sellable@sellable"');
1907
1973
  after = removeTomlSection(after, 'plugins."sellable@sellable-local"');
1908
- for (const agent of [...codexCustomAgents(), ...legacyCodexCustomAgents()]) {
1974
+ for (const agent of [
1975
+ ...codexCustomAgents(),
1976
+ ...legacyCodexCustomAgents(),
1977
+ ]) {
1909
1978
  after = removeTomlSection(after, `agents.${agent.name}`);
1910
1979
  }
1911
1980
  // Collapse 3+ blank lines that the removals may leave behind.
@@ -1955,7 +2024,10 @@ function runUninstall() {
1955
2024
  skipped.push(`Claude Code CLI not found`);
1956
2025
  }
1957
2026
 
1958
- for (const agent of [...claudeCustomAgents(), ...legacyClaudeCustomAgents()]) {
2027
+ for (const agent of [
2028
+ ...claudeCustomAgents(),
2029
+ ...legacyClaudeCustomAgents(),
2030
+ ]) {
1959
2031
  const agentPath = join(claudeHome(), "agents", agent.filename);
1960
2032
  if (!existsSync(agentPath)) continue;
1961
2033
  try {
@@ -1967,6 +2039,18 @@ function runUninstall() {
1967
2039
  );
1968
2040
  }
1969
2041
  }
2042
+ for (const command of legacyClaudeCommands()) {
2043
+ const commandPath = join(claudeHome(), "commands", command.filename);
2044
+ if (!existsSync(commandPath)) continue;
2045
+ try {
2046
+ rmSync(commandPath, { force: true });
2047
+ removed.push(`${commandPath}`);
2048
+ } catch (err) {
2049
+ console.log(
2050
+ ` ${C.yellow}!${C.reset} Could not remove ${commandPath}: ${err instanceof Error ? err.message : String(err)}`
2051
+ );
2052
+ }
2053
+ }
1970
2054
 
1971
2055
  // 3) Surgical removal of Sellable-installed artifacts inside ~/.sellable/
1972
2056
  const sellableDir = join(homedir(), ".sellable");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/install",
3
- "version": "0.1.77",
3
+ "version": "0.1.79",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code and Codex",
6
6
  "bin": {
@@ -66,10 +66,10 @@ allowed-tools:
66
66
 
67
67
  Use this as the customer-facing entrypoint for Sellable campaign creation.
68
68
 
69
- CampaignOffer state is canonical; disk artifacts are a debug trail. The
70
- internal create-campaign-v2 flow still writes the diagnostics, and all 14 disk
71
- artifacts remain as debug outputs, but resume, gating, and handoff read campaign
72
- state first. The
69
+ CampaignOffer state and the watch link are the customer-facing source of truth.
70
+ Disk artifacts are optional debug/UAT diagnostics; normal customer runs should
71
+ not create, link, or surface local draft files unless the user explicitly asks
72
+ for them. Resume, gating, and handoff read campaign state first. The
73
73
  watchable campaign exists after the short brief; lead import is bounded to the
74
74
  first review batch, and enrichment/message generation waits until rubrics and
75
75
  the approved message template are saved on the campaign.
@@ -147,13 +147,12 @@ Use rendered Markdown for user review surfaces, not fenced code blocks. Keep
147
147
  lines short, use indexed section labels and bullets, and translate internal
148
148
  sourcing terms into plain language.
149
149
 
150
- Every approval gate must include artifact access after the readable inline
151
- content. Show a short `Open artifact:` line with the one key clickable markdown
152
- link for that stage. Do not show raw filesystem paths unless links cannot be
153
- created or the user asks. Do this for brief approval, lead-source
154
- approval/review, lead-filter review, and message review.
155
- The link is for deeper inspection; never use it as a substitute for showing the
156
- content in chat.
150
+ Every approval gate must include live campaign access after the readable inline
151
+ content. Show a short `Watch link:` line once the campaign shell exists. In
152
+ normal customer runs, do not show `Open artifact:` lines, raw filesystem paths,
153
+ or local draft filenames. Local artifacts are debug/UAT-only unless the user asks
154
+ for them. The link is for deeper inspection; never use it as a substitute for
155
+ showing the content in chat.
157
156
 
158
157
  Never mention MCP namespaces, prompt chunking, plugin cache paths, missing
159
158
  linked skill versions, runbooks, or local skill files in normal customer-facing
@@ -503,9 +502,16 @@ updates.
503
502
  `message-validation.md` proves the message-review safety-gate workflow ran,
504
503
  `message-review.md` approves the template, rubrics are saved, and the
505
504
  approved message set is synced into the campaign brief.
506
- 6. Keep `selectedLeadListId` as the source list and `workflowTableId` as the
505
+ 6. The main thread owns watch navigation. Call
506
+ `mcp__sellable__update_campaign({ campaignId, currentStep })` before major
507
+ visible work so the user can watch progress in the app: `create-offer` for
508
+ the brief, `pick-provider` or the selected provider step while sourcing,
509
+ `filter-choice` after the 10-row review batch, `messages` or
510
+ `auto-execute-messaging` for message work, `validate-sample` for validation,
511
+ and `awaiting-user-greenlight` for Settings. Do not advance the step backward.
512
+ 7. Keep `selectedLeadListId` as the source list and `workflowTableId` as the
507
513
  campaign table. Do not use disk files as the post-mint source of truth.
508
- 7. Do not ask the user to run another command.
514
+ 8. Do not ask the user to run another command.
509
515
 
510
516
  ## Fallback
511
517