@sellable/install 0.1.210 → 0.1.212
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/bin/sellable-install.mjs +156 -41
- package/package.json +1 -1
- package/skill-templates/create-campaign.md +66 -17
package/bin/sellable-install.mjs
CHANGED
|
@@ -72,8 +72,9 @@ const CODEX_PLUGIN_COMPAT_VERSIONS = [
|
|
|
72
72
|
"0.1.40",
|
|
73
73
|
"0.1.41",
|
|
74
74
|
];
|
|
75
|
-
const
|
|
75
|
+
const RAW_INSTALL_PACKAGE_SPEC =
|
|
76
76
|
process.env.SELLABLE_INSTALL_PACKAGE_SPEC || "@sellable/install@latest";
|
|
77
|
+
const INSTALL_PACKAGE_SPEC = normalizeWindowsPackageSpec(RAW_INSTALL_PACKAGE_SPEC);
|
|
77
78
|
|
|
78
79
|
const useColor = Boolean(output.isTTY) && process.env.NO_COLOR === undefined;
|
|
79
80
|
const C = {
|
|
@@ -89,6 +90,15 @@ const C = {
|
|
|
89
90
|
|
|
90
91
|
let VERBOSE = false;
|
|
91
92
|
|
|
93
|
+
function normalizeWindowsPackageSpec(value) {
|
|
94
|
+
if (typeof value !== "string") return value;
|
|
95
|
+
if (/^[A-Za-z]:\//.test(value)) return value.replace(/\//g, "\\");
|
|
96
|
+
if (/^\/[A-Za-z]\//.test(value)) {
|
|
97
|
+
return `${value[1]}:${value.slice(2)}`.replace(/\//g, "\\");
|
|
98
|
+
}
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
|
|
92
102
|
function logVerbose(line) {
|
|
93
103
|
if (VERBOSE) console.log(line);
|
|
94
104
|
}
|
|
@@ -263,7 +273,7 @@ function parseArgs(argv) {
|
|
|
263
273
|
} else if (arg === "--api-url") {
|
|
264
274
|
opts.apiUrl = next();
|
|
265
275
|
} else if (arg === "--mcp-package") {
|
|
266
|
-
opts.mcpPackage = next();
|
|
276
|
+
opts.mcpPackage = normalizeWindowsPackageSpec(next());
|
|
267
277
|
} else if (arg === "--local-command") {
|
|
268
278
|
opts.localCommand = next();
|
|
269
279
|
} else if (arg === "--hosted-url") {
|
|
@@ -771,7 +781,54 @@ function codexSkillOpenAiYaml(displayName, description) {
|
|
|
771
781
|
`;
|
|
772
782
|
}
|
|
773
783
|
|
|
774
|
-
function
|
|
784
|
+
function installedHostContract(host, commandName) {
|
|
785
|
+
if (host === "codex") {
|
|
786
|
+
return `## Installed Host Contract
|
|
787
|
+
|
|
788
|
+
This installed skill is running in Codex. When the shared workflow body or
|
|
789
|
+
fallback text mentions both Claude Code and Codex for internal parity, choose
|
|
790
|
+
the Codex instruction for customer-facing language and host functions.
|
|
791
|
+
|
|
792
|
+
- Customer-facing command: \`$sellable:${commandName}\`
|
|
793
|
+
- Structured question function: \`request_user_input\`
|
|
794
|
+
- Bootstrap host label: \`host: "Codex"\`
|
|
795
|
+
- Install/reload blocker label: Codex install/reload problem
|
|
796
|
+
- Reload instruction: fully quit and reopen Codex Desktop, then start a new thread
|
|
797
|
+
|
|
798
|
+
Do not tell Codex users to run \`/sellable:${commandName}\`, use
|
|
799
|
+
\`AskUserQuestion\`, or restart Claude Code. Do not describe this run as Claude Code.`;
|
|
800
|
+
}
|
|
801
|
+
if (host === "claude") {
|
|
802
|
+
return `## Installed Host Contract
|
|
803
|
+
|
|
804
|
+
This installed command is running in Claude Code. When the shared workflow body
|
|
805
|
+
or fallback text mentions both Claude Code and Codex for internal parity, choose
|
|
806
|
+
the Claude Code instruction for customer-facing language and host functions.
|
|
807
|
+
|
|
808
|
+
- Customer-facing command: \`/sellable:${commandName}\`
|
|
809
|
+
- Structured question function: \`AskUserQuestion\`
|
|
810
|
+
- Bootstrap host label: \`host: "Claude Code"\`
|
|
811
|
+
- Install/reload blocker label: Claude Code install/reload problem
|
|
812
|
+
- Reload instruction: fully quit and reopen Claude Code, then start a new session
|
|
813
|
+
|
|
814
|
+
Do not tell Claude Code users to run \`$sellable:${commandName}\`, use
|
|
815
|
+
\`request_user_input\`, or restart Codex Desktop. Do not describe this run as Codex.`;
|
|
816
|
+
}
|
|
817
|
+
return "";
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
function stampInstalledHost(markdown, host, commandName) {
|
|
821
|
+
const preamble = installedHostContract(host, commandName);
|
|
822
|
+
if (!preamble || markdown.includes("## Installed Host Contract")) {
|
|
823
|
+
return markdown;
|
|
824
|
+
}
|
|
825
|
+
return String(markdown).replace(
|
|
826
|
+
/(^# .+\n\n)/m,
|
|
827
|
+
`$1${preamble}\n\n`
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
function createCampaignSkillMd(host = "shared") {
|
|
775
832
|
// Single source of truth: ../skill-templates/create-campaign.md, which is
|
|
776
833
|
// copied from the canonical mcp/sellable/skills/create-campaign/SKILL.md at
|
|
777
834
|
// publish time via scripts/sync-skill-templates.mjs (prepublishOnly hook).
|
|
@@ -786,12 +843,16 @@ function createCampaignSkillMd() {
|
|
|
786
843
|
"create-campaign.md"
|
|
787
844
|
);
|
|
788
845
|
if (existsSync(templatePath)) {
|
|
789
|
-
return
|
|
846
|
+
return stampInstalledHost(
|
|
847
|
+
readFileSync(templatePath, "utf8"),
|
|
848
|
+
host,
|
|
849
|
+
"create-campaign"
|
|
850
|
+
);
|
|
790
851
|
}
|
|
791
852
|
} catch {
|
|
792
853
|
// fall through to hardcoded fallback below
|
|
793
854
|
}
|
|
794
|
-
return `---
|
|
855
|
+
return stampInstalledHost(`---
|
|
795
856
|
name: create-campaign
|
|
796
857
|
description: Create a Sellable campaign through the approval-gated workflow.
|
|
797
858
|
allowed-tools:
|
|
@@ -814,17 +875,11 @@ person/company this campaign is for, then I’ll turn that into a campaign brief
|
|
|
814
875
|
before anything is created.
|
|
815
876
|
\`\`\`
|
|
816
877
|
|
|
817
|
-
Exception: if \`bootstrap_create_campaign.modelQuality.status === "warn"
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
message generation, or launch review. If \`metadataStale === true\`, continue
|
|
823
|
-
normally and do not ask the user to switch.
|
|
824
|
-
|
|
825
|
-
If \`bootstrap_create_campaign.modelQuality.metadataStale === true\`, continue
|
|
826
|
-
normally. Do not ask the user to switch models; this is an accepted Codex host
|
|
827
|
-
metadata mismatch.
|
|
878
|
+
Exception: if \`bootstrap_create_campaign.modelQuality.status === "warn"\`, the
|
|
879
|
+
first visible campaign message must be the model-quality warning from
|
|
880
|
+
\`modelQuality.message\`. Only trust that warning when bootstrap received active
|
|
881
|
+
turn/runtime metadata or an explicit user-confirmed model. Do not warn from
|
|
882
|
+
config defaults, stale host labels, or inferred model names.
|
|
828
883
|
|
|
829
884
|
If a linked/local skill file is stale or missing, silently use the installed
|
|
830
885
|
\`sellable@sellable\` plugin copy. Do not tell the user about the stale link,
|
|
@@ -842,6 +897,56 @@ clear business decisions, tradeoffs, and approval gates. Use product language:
|
|
|
842
897
|
- "I can create a draft shell for you to watch with approval gates before
|
|
843
898
|
sourcing", not mutation jargon
|
|
844
899
|
|
|
900
|
+
## Active Model Metadata
|
|
901
|
+
|
|
902
|
+
Before calling \`bootstrap_create_campaign\`, collect the active host model data
|
|
903
|
+
only from a source that can describe this turn:
|
|
904
|
+
|
|
905
|
+
- Codex: if \`mcp__node_repl__js\` is available, inspect only
|
|
906
|
+
\`nodeRepl.requestMeta["x-codex-turn-metadata"].model\` and
|
|
907
|
+
\`nodeRepl.requestMeta["x-codex-turn-metadata"].reasoning_effort\`. Pass those
|
|
908
|
+
values as \`model\` and \`reasoningEffort\`, with
|
|
909
|
+
\`modelMetadataSource: "codex_turn_metadata"\`.
|
|
910
|
+
- Codex fallback/cross-check: if active turn metadata is unavailable, you may
|
|
911
|
+
inspect \`~/.codex/config.toml\` for \`model\` and
|
|
912
|
+
\`model_reasoning_effort\`, but pass
|
|
913
|
+
\`modelMetadataSource: "codex_config_fallback"\` and do not treat it as a
|
|
914
|
+
reason to ask the user to switch models. Active turn metadata wins if it
|
|
915
|
+
differs from config.
|
|
916
|
+
- Claude Code / Opus: use active Claude runtime metadata only if the current
|
|
917
|
+
host exposes model and effort for this same session, with
|
|
918
|
+
\`modelMetadataSource: "claude_runtime_metadata"\`. Current Claude Code MCP
|
|
919
|
+
tool calls may not include model or effort metadata; when they do not, omit
|
|
920
|
+
\`model\`, \`reasoningEffort\`, and \`modelMetadataSource\`.
|
|
921
|
+
- Claude Code session-context self-report: if your current Claude session
|
|
922
|
+
context explicitly states both the exact model ID and effort/thinking level,
|
|
923
|
+
report it internally in this shape and pass it to bootstrap with
|
|
924
|
+
\`modelMetadataSource: "claude_session_context"\`:
|
|
925
|
+
|
|
926
|
+
\`\`\`text
|
|
927
|
+
- Model (name): ...
|
|
928
|
+
- Model (ID): ...
|
|
929
|
+
- Reasoning effort: ...
|
|
930
|
+
- Source: active Claude Code session context
|
|
931
|
+
\`\`\`
|
|
932
|
+
|
|
933
|
+
Use this only when the values are explicitly present in the current session
|
|
934
|
+
context. Do not infer an ID from the friendly name, do not infer effort from
|
|
935
|
+
\`alwaysThinkingEnabled\`, and do not show this self-report to the user during
|
|
936
|
+
normal campaign setup.
|
|
937
|
+
- Do not run a nested \`claude -p\`, inspect \`~/.claude/settings.json\`, or read
|
|
938
|
+
Claude CLI defaults as proof of the user's active Claude Code session. Those
|
|
939
|
+
checks can validate a new child session or saved defaults, but not this
|
|
940
|
+
session's actual model and effort.
|
|
941
|
+
- If the user explicitly provides active Claude \`/status\` or \`/model\` output
|
|
942
|
+
that includes both model and effort, pass it with
|
|
943
|
+
\`modelMetadataSource: "user_confirmed"\`. If it is missing either model or
|
|
944
|
+
effort, treat the metadata as unknown and continue.
|
|
945
|
+
|
|
946
|
+
Never invent the model or reasoning effort. Never pass config defaults as active
|
|
947
|
+
metadata. If bootstrap returns \`modelQuality.status === "unknown"\`, continue
|
|
948
|
+
without asking the user to switch models.
|
|
949
|
+
|
|
845
950
|
When explaining source decisions, show the concrete counts behind the
|
|
846
951
|
logic: lanes searched, timeframe, raw result counts, finalist posts or preview
|
|
847
952
|
rows, sampled people, sampled fits as n/N (%), estimated usable people, and the
|
|
@@ -1263,13 +1368,19 @@ updates.
|
|
|
1263
1368
|
- Do not call \`mcp__sellable__get_campaigns\`.
|
|
1264
1369
|
- Do not call \`mcp__sellable__get_campaign\` to hunt for IDs.
|
|
1265
1370
|
- Do not call \`mcp__sellable__create_campaign({ campaignId: ... })\` unless the user supplied that id.
|
|
1266
|
-
5. Call \`mcp__sellable__bootstrap_create_campaign({ flowVersion: "v2", campaignId?, host?, model?, reasoningEffort? })\`.
|
|
1267
|
-
Pass
|
|
1371
|
+
5. Call \`mcp__sellable__bootstrap_create_campaign({ flowVersion: "v2", campaignId?, host?, model?, reasoningEffort?, modelMetadataSource? })\`.
|
|
1372
|
+
Pass model metadata only when collected by the Active Model Metadata rules
|
|
1373
|
+
above. For Codex active turn metadata, pass
|
|
1374
|
+
\`modelMetadataSource: "codex_turn_metadata"\`. For explicit Claude session
|
|
1375
|
+
context, pass \`modelMetadataSource: "claude_session_context"\`. For explicit
|
|
1376
|
+
user-confirmed Claude \`/status\` or \`/model\` output, pass
|
|
1377
|
+
\`modelMetadataSource: "user_confirmed"\` only when it includes both model and
|
|
1378
|
+
effort.
|
|
1268
1379
|
6. If \`safeToProceed !== true\`, stop and show \`blockingErrors\` + \`nextStep\`.
|
|
1269
|
-
7. If \`modelQuality.status === "warn"
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1380
|
+
7. If \`modelQuality.status === "warn"\`, show \`modelQuality.message\` before
|
|
1381
|
+
any setup/research and wait for the user to switch or explicitly continue. If
|
|
1382
|
+
\`modelQuality.status === "unknown"\`, continue; do not tell the user to
|
|
1383
|
+
switch models.
|
|
1273
1384
|
|
|
1274
1385
|
## Execute Workflow
|
|
1275
1386
|
|
|
@@ -1350,10 +1461,10 @@ updates.
|
|
|
1350
1461
|
If subskill lookup fails, use
|
|
1351
1462
|
\`mcp__sellable__search_subskill_prompts({ query: "create-campaign-v2" })\`,
|
|
1352
1463
|
then retry \`get_subskill_prompt\`.
|
|
1353
|
-
|
|
1464
|
+
`, host, "create-campaign");
|
|
1354
1465
|
}
|
|
1355
1466
|
|
|
1356
|
-
function createAbTestSkillMd() {
|
|
1467
|
+
function createAbTestSkillMd(host = "shared") {
|
|
1357
1468
|
try {
|
|
1358
1469
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
1359
1470
|
const templatePath = join(
|
|
@@ -1363,12 +1474,16 @@ function createAbTestSkillMd() {
|
|
|
1363
1474
|
"create-ab-test.md"
|
|
1364
1475
|
);
|
|
1365
1476
|
if (existsSync(templatePath)) {
|
|
1366
|
-
return
|
|
1477
|
+
return stampInstalledHost(
|
|
1478
|
+
readFileSync(templatePath, "utf8"),
|
|
1479
|
+
host,
|
|
1480
|
+
"create-ab-test"
|
|
1481
|
+
);
|
|
1367
1482
|
}
|
|
1368
1483
|
} catch {
|
|
1369
1484
|
// fall through to hardcoded fallback below
|
|
1370
1485
|
}
|
|
1371
|
-
return `---
|
|
1486
|
+
return stampInstalledHost(`---
|
|
1372
1487
|
name: create-ab-test
|
|
1373
1488
|
description: Create a Sellable campaign A/B test from a clean source lead list.
|
|
1374
1489
|
visibility: public
|
|
@@ -1384,11 +1499,11 @@ allowed-tools:
|
|
|
1384
1499
|
# Sellable Create A/B Test
|
|
1385
1500
|
|
|
1386
1501
|
Use \`prepare_campaign_ab_test\` to create clean A/B split lead lists and review-copy campaigns. Do not call \`export_table_csv\` from generated campaign workflow tables as lead source data, and do not call \`start_campaign\`.
|
|
1387
|
-
|
|
1502
|
+
`, host, "create-ab-test");
|
|
1388
1503
|
}
|
|
1389
1504
|
|
|
1390
|
-
function genericSellableSkillMd({ name, title, description }) {
|
|
1391
|
-
return `---
|
|
1505
|
+
function genericSellableSkillMd({ name, title, description, host = "shared" }) {
|
|
1506
|
+
return stampInstalledHost(`---
|
|
1392
1507
|
name: ${name}
|
|
1393
1508
|
description: ${yamlString(description)}
|
|
1394
1509
|
allowed-tools:
|
|
@@ -1423,11 +1538,11 @@ Desktop, then start a new thread.
|
|
|
1423
1538
|
## MCP Prompt Fallback
|
|
1424
1539
|
|
|
1425
1540
|
If subskill lookup fails, use \`mcp__sellable__search_subskill_prompts({ query: "${name}" })\`, then retry \`get_subskill_prompt\`.
|
|
1426
|
-
|
|
1541
|
+
`, host, name);
|
|
1427
1542
|
}
|
|
1428
1543
|
|
|
1429
|
-
function foundationSkillMd() {
|
|
1430
|
-
return `---
|
|
1544
|
+
function foundationSkillMd(host = "shared") {
|
|
1545
|
+
return stampInstalledHost(`---
|
|
1431
1546
|
name: foundation
|
|
1432
1547
|
description: ${yamlString(FOUNDATION_SKILL_DESCRIPTION)}
|
|
1433
1548
|
allowed-tools:
|
|
@@ -1486,11 +1601,11 @@ Desktop, then start a new thread.
|
|
|
1486
1601
|
If exact subskill lookup fails, use
|
|
1487
1602
|
\`mcp__sellable__search_subskill_prompts({ query: "foundation", includePublic: true, includeInternal: true })\`,
|
|
1488
1603
|
then retry \`get_subskill_prompt\`.
|
|
1489
|
-
|
|
1604
|
+
`, host, "foundation");
|
|
1490
1605
|
}
|
|
1491
1606
|
|
|
1492
|
-
function contentSkillMd() {
|
|
1493
|
-
return `---
|
|
1607
|
+
function contentSkillMd(host = "shared") {
|
|
1608
|
+
return stampInstalledHost(`---
|
|
1494
1609
|
name: content
|
|
1495
1610
|
description: Add transcripts and rough ideas, cluster recurring themes, ideate post seeds, and hand draft requests to create-post.
|
|
1496
1611
|
allowed-tools:
|
|
@@ -1556,11 +1671,11 @@ Desktop, then start a new thread.
|
|
|
1556
1671
|
If exact subskill lookup fails, use
|
|
1557
1672
|
\`mcp__sellable__search_subskill_prompts({ query: "content", includePublic: true, includeInternal: true })\`,
|
|
1558
1673
|
then retry \`get_subskill_prompt\`.
|
|
1559
|
-
|
|
1674
|
+
`, host, "content");
|
|
1560
1675
|
}
|
|
1561
1676
|
|
|
1562
|
-
function createPostSkillMd() {
|
|
1563
|
-
return `---
|
|
1677
|
+
function createPostSkillMd(host = "shared") {
|
|
1678
|
+
return stampInstalledHost(`---
|
|
1564
1679
|
name: create-post
|
|
1565
1680
|
description: Capture rough LinkedIn post ideas, develop a valuable premise, research current hooks and audience tension, then save validated drafts in the user's voice.
|
|
1566
1681
|
allowed-tools:
|
|
@@ -1630,7 +1745,7 @@ Desktop, then start a new thread.
|
|
|
1630
1745
|
If exact subskill lookup fails, use
|
|
1631
1746
|
\`mcp__sellable__search_subskill_prompts({ query: "create-post", includePublic: true, includeInternal: true })\`,
|
|
1632
1747
|
then retry \`get_subskill_prompt\`.
|
|
1633
|
-
|
|
1748
|
+
`, host, "create-post");
|
|
1634
1749
|
}
|
|
1635
1750
|
|
|
1636
1751
|
function createCampaignSoulMd() {
|
|
@@ -1827,7 +1942,7 @@ function codexPluginSkills() {
|
|
|
1827
1942
|
dir: "sellable-create-campaign",
|
|
1828
1943
|
displayName: "Sellable Create Campaign",
|
|
1829
1944
|
description: "Create a Sellable campaign with approval gates",
|
|
1830
|
-
skillMd: createCampaignSkillMd(),
|
|
1945
|
+
skillMd: createCampaignSkillMd("codex"),
|
|
1831
1946
|
soulMd: createCampaignSoulMd(),
|
|
1832
1947
|
},
|
|
1833
1948
|
{
|
|
@@ -2051,7 +2166,7 @@ function claudeCommands() {
|
|
|
2051
2166
|
filename: join("sellable", "create-campaign.md"),
|
|
2052
2167
|
description: "Create a Sellable campaign through the approval-gated workflow.",
|
|
2053
2168
|
argumentHint: "[campaign goal, company, or offer]",
|
|
2054
|
-
skillMd: createCampaignSkillMd(),
|
|
2169
|
+
skillMd: createCampaignSkillMd("claude"),
|
|
2055
2170
|
allowedTools: ["AskUserQuestion", "Task", ...CREATE_CAMPAIGN_ALLOWED_TOOLS],
|
|
2056
2171
|
},
|
|
2057
2172
|
{
|
package/package.json
CHANGED
|
@@ -179,17 +179,11 @@ person/company this campaign is for, then I’ll turn that into a campaign brief
|
|
|
179
179
|
before we move into lead sourcing.
|
|
180
180
|
```
|
|
181
181
|
|
|
182
|
-
Exception: if `bootstrap_create_campaign.modelQuality.status === "warn"
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
message generation, or launch review. If `metadataStale === true`, continue
|
|
188
|
-
normally and do not ask the user to switch.
|
|
189
|
-
|
|
190
|
-
If `bootstrap_create_campaign.modelQuality.metadataStale === true`, continue
|
|
191
|
-
normally. Do not ask the user to switch models; this is an accepted Codex host
|
|
192
|
-
metadata mismatch.
|
|
182
|
+
Exception: if `bootstrap_create_campaign.modelQuality.status === "warn"`, the
|
|
183
|
+
first visible campaign message must be the model-quality warning from
|
|
184
|
+
`modelQuality.message`. Only trust that warning when bootstrap received active
|
|
185
|
+
turn/runtime metadata or an explicit user-confirmed model. Do not warn from
|
|
186
|
+
config defaults, stale host labels, or inferred model names.
|
|
193
187
|
|
|
194
188
|
If a linked/local skill file is stale or missing, silently use the installed
|
|
195
189
|
`sellable@sellable` plugin copy. Do not tell the user about the stale link,
|
|
@@ -207,6 +201,55 @@ clear business decisions, tradeoffs, and approval gates. Use product language:
|
|
|
207
201
|
- "I can create a draft shell for you to watch with approval gates before
|
|
208
202
|
sourcing", not mutation jargon
|
|
209
203
|
|
|
204
|
+
## Active Model Metadata
|
|
205
|
+
|
|
206
|
+
Before calling `bootstrap_create_campaign`, collect the active host model data
|
|
207
|
+
only from a source that can describe this turn:
|
|
208
|
+
|
|
209
|
+
- Codex: if `mcp__node_repl__js` is available, inspect only
|
|
210
|
+
`nodeRepl.requestMeta["x-codex-turn-metadata"].model` and
|
|
211
|
+
`nodeRepl.requestMeta["x-codex-turn-metadata"].reasoning_effort`. Pass those
|
|
212
|
+
values as `model` and `reasoningEffort`, with
|
|
213
|
+
`modelMetadataSource: "codex_turn_metadata"`.
|
|
214
|
+
- Codex fallback/cross-check: if active turn metadata is unavailable, you may
|
|
215
|
+
inspect `~/.codex/config.toml` for `model` and `model_reasoning_effort`, but
|
|
216
|
+
pass `modelMetadataSource: "codex_config_fallback"` and do not treat it as a
|
|
217
|
+
reason to ask the user to switch models. Active turn metadata wins if it
|
|
218
|
+
differs from config.
|
|
219
|
+
- Claude Code / Opus: use active Claude runtime metadata only if the current
|
|
220
|
+
host exposes model and effort for this same session, with
|
|
221
|
+
`modelMetadataSource: "claude_runtime_metadata"`. Current Claude Code MCP
|
|
222
|
+
tool calls may not include model or effort metadata; when they do not, omit
|
|
223
|
+
`model`, `reasoningEffort`, and `modelMetadataSource`.
|
|
224
|
+
- Claude Code session-context self-report: if your current Claude session
|
|
225
|
+
context explicitly states both the exact model ID and effort/thinking level,
|
|
226
|
+
report it internally in this shape and pass it to bootstrap with
|
|
227
|
+
`modelMetadataSource: "claude_session_context"`:
|
|
228
|
+
|
|
229
|
+
```text
|
|
230
|
+
- Model (name): ...
|
|
231
|
+
- Model (ID): ...
|
|
232
|
+
- Reasoning effort: ...
|
|
233
|
+
- Source: active Claude Code session context
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Use this only when the values are explicitly present in the current session
|
|
237
|
+
context. Do not infer an ID from the friendly name, do not infer effort from
|
|
238
|
+
`alwaysThinkingEnabled`, and do not show this self-report to the user during
|
|
239
|
+
normal campaign setup.
|
|
240
|
+
- Do not run a nested `claude -p`, inspect `~/.claude/settings.json`, or read
|
|
241
|
+
Claude CLI defaults as proof of the user's active Claude Code session. Those
|
|
242
|
+
checks can validate a new child session or saved defaults, but not this
|
|
243
|
+
session's actual model and effort.
|
|
244
|
+
- If the user explicitly provides active Claude `/status` or `/model` output
|
|
245
|
+
that includes both model and effort, pass it with
|
|
246
|
+
`modelMetadataSource: "user_confirmed"`. If it is missing either model or
|
|
247
|
+
effort, treat the metadata as unknown and continue.
|
|
248
|
+
|
|
249
|
+
Never invent the model or reasoning effort. Never pass config defaults as active
|
|
250
|
+
metadata. If bootstrap returns `modelQuality.status === "unknown"`, continue
|
|
251
|
+
without asking the user to switch models.
|
|
252
|
+
|
|
210
253
|
Approval and safety copy should be tasteful. State what the current approval
|
|
211
254
|
covers once, in one short sentence, then move on. Do not append repeated
|
|
212
255
|
"nothing starts / no leads import / no sending" disclaimers to routine progress
|
|
@@ -938,13 +981,19 @@ updates.
|
|
|
938
981
|
- Do not call `mcp__sellable__get_campaigns`.
|
|
939
982
|
- Do not call `mcp__sellable__get_campaign` to hunt for IDs.
|
|
940
983
|
- Do not call `mcp__sellable__create_campaign({ campaignId: ... })` unless the user supplied that id.
|
|
941
|
-
6. Call `mcp__sellable__bootstrap_create_campaign({ flowVersion: "v2", campaignId?, host?, model?, reasoningEffort? })`.
|
|
942
|
-
Pass
|
|
984
|
+
6. Call `mcp__sellable__bootstrap_create_campaign({ flowVersion: "v2", campaignId?, host?, model?, reasoningEffort?, modelMetadataSource? })`.
|
|
985
|
+
Pass model metadata only when collected by the Active Model Metadata rules
|
|
986
|
+
above. For Codex active turn metadata, pass
|
|
987
|
+
`modelMetadataSource: "codex_turn_metadata"`. For explicit Claude session
|
|
988
|
+
context, pass `modelMetadataSource: "claude_session_context"`. For explicit
|
|
989
|
+
user-confirmed Claude `/status` or `/model` output, pass
|
|
990
|
+
`modelMetadataSource: "user_confirmed"` only when it includes both model and
|
|
991
|
+
effort.
|
|
943
992
|
7. If `safeToProceed !== true`, stop and show `blockingErrors` + `nextStep`.
|
|
944
|
-
8. If `modelQuality.status === "warn"
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
993
|
+
8. If `modelQuality.status === "warn"`, show `modelQuality.message` before any
|
|
994
|
+
setup/research and wait for the user to switch or explicitly continue. If
|
|
995
|
+
`modelQuality.status === "unknown"`, continue; do not tell the user to
|
|
996
|
+
switch models.
|
|
948
997
|
|
|
949
998
|
## Execute Workflow
|
|
950
999
|
|