@sellable/install 0.1.120 → 0.1.122

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 CHANGED
@@ -6,6 +6,16 @@ Installs Sellable MCP for Claude Code and Codex.
6
6
  npx -y @sellable/install@latest --host all
7
7
  ```
8
8
 
9
+ Paste that command in your terminal, not inside the Codex chat. Mac/Linux
10
+ users can use Terminal. Windows users can use PowerShell or Windows Terminal;
11
+ if PowerShell blocks `npx`, run:
12
+
13
+ ```powershell
14
+ npx.cmd -y @sellable/install@latest --host all
15
+ ```
16
+
17
+ After install, restart Codex Desktop so the Sellable skill appears.
18
+
9
19
  After install, `sellable create` is a terminal helper that prints the correct
10
20
  agent command for launching a campaign:
11
21
 
@@ -60,9 +60,14 @@ currentStep: "signal-discovery" })` before sampling so the watched Signal
60
60
  sampled/projected headline-fit rate clears the 10% planning floor. Treat the
61
61
  10% floor as a reject threshold, not as the scrape-count denominator when the
62
62
  actual sample rate is higher.
63
- 8. Select/promote enough right-content posts to plausibly hit the target. If the
64
- warm Signals pool is useful but too small, return the expected warm range and
65
- recommend Sales Nav/Prospeo for scale instead of padding with noisy posts.
63
+ 8. Select/promote enough right-content posts to plausibly hit the target. After
64
+ the sample math is known, treat the promoted sample set and final scrape set
65
+ as separate: recommend the smallest right-content post subset whose
66
+ scrapable/reachable engagers clears the required engager count, with a modest
67
+ buffer when needed. If one 1,200+ engager post clears a ~1,000-engager target,
68
+ recommend scraping that one post, not all 3 sample posts. If the warm Signals
69
+ pool is useful but too small, return the expected warm range and recommend
70
+ Sales Nav/Prospeo for scale instead of padding with noisy posts.
66
71
  9. Return false positives and dead ends explicitly.
67
72
 
68
73
  Return a concise structured result with:
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { spawnSync } from "node:child_process";
3
3
  import {
4
+ cpSync,
4
5
  existsSync,
5
6
  mkdirSync,
6
7
  readdirSync,
@@ -30,16 +31,6 @@ function getInstallVersion() {
30
31
  }
31
32
  }
32
33
 
33
- function getMcpVersion() {
34
- try {
35
- const r = spawnSync("npm", ["view", "@sellable/mcp", "version"], {
36
- encoding: "utf8",
37
- timeout: 5000,
38
- });
39
- if (r.status === 0 && r.stdout) return r.stdout.trim();
40
- } catch {}
41
- return "latest";
42
- }
43
34
  const CODEX_PLUGIN_VERSION = "0.1.33";
44
35
  const CODEX_PLUGIN_COMPAT_VERSIONS = [
45
36
  "0.1.8",
@@ -282,13 +273,59 @@ function run(command, args, opts = {}) {
282
273
  return result;
283
274
  }
284
275
 
285
- function commandExists(command) {
286
- const result = spawnSync("sh", ["-lc", `command -v ${command}`], {
287
- encoding: "utf8",
288
- });
276
+ function isWindowsPlatform(platform = process.platform) {
277
+ return platform === "win32";
278
+ }
279
+
280
+ function packageRunnerCommand(platform = process.platform) {
281
+ return isWindowsPlatform(platform) ? "npx.cmd" : "npx";
282
+ }
283
+
284
+ function packageManagerCommand(platform = process.platform) {
285
+ return isWindowsPlatform(platform) ? "npm.cmd" : "npm";
286
+ }
287
+
288
+ function commandExists(command, platform = process.platform) {
289
+ const result = isWindowsPlatform(platform)
290
+ ? spawnSync("where.exe", [command], {
291
+ encoding: "utf8",
292
+ })
293
+ : spawnSync("sh", ["-lc", `command -v ${command}`], {
294
+ encoding: "utf8",
295
+ });
289
296
  return result.status === 0;
290
297
  }
291
298
 
299
+ function commandExistsDetails(command, platform = process.platform) {
300
+ const result = isWindowsPlatform(platform)
301
+ ? spawnSync("where.exe", [command], {
302
+ encoding: "utf8",
303
+ })
304
+ : spawnSync("sh", ["-lc", `command -v ${command}`], {
305
+ encoding: "utf8",
306
+ });
307
+ return {
308
+ exists: result.status === 0,
309
+ stdout: (result.stdout || "").trim(),
310
+ platform,
311
+ };
312
+ }
313
+
314
+ function getMcpVersion() {
315
+ try {
316
+ const r = spawnSync(
317
+ packageManagerCommand(),
318
+ ["view", "@sellable/mcp", "version"],
319
+ {
320
+ encoding: "utf8",
321
+ timeout: 5000,
322
+ }
323
+ );
324
+ if (r.status === 0 && r.stdout) return r.stdout.trim();
325
+ } catch {}
326
+ return "latest";
327
+ }
328
+
292
329
  function authPath() {
293
330
  return join(homedir(), ".sellable", "config.json");
294
331
  }
@@ -420,7 +457,26 @@ function ensureSymlink(target, linkPath, opts) {
420
457
  // ignore
421
458
  }
422
459
  const rel = relative(dirname(linkPath), target);
423
- symlinkSync(rel, linkPath, "dir");
460
+ try {
461
+ symlinkSync(rel, linkPath, "dir");
462
+ } catch (err) {
463
+ const code = err && typeof err === "object" ? err.code : "";
464
+ const message = err instanceof Error ? err.message : String(err);
465
+ const isDenied =
466
+ code === "EPERM" ||
467
+ code === "EACCES" ||
468
+ /privilege|permission|operation not permitted/i.test(message);
469
+
470
+ if (!isWindowsPlatform() || !isDenied) {
471
+ throw err;
472
+ }
473
+
474
+ logVerbose(
475
+ `${C.grey}+ symlink denied on Windows; copying compatibility cache ${linkPath}${C.reset}`
476
+ );
477
+ rmSync(linkPath, { recursive: true, force: true });
478
+ cpSync(target, linkPath, { recursive: true, force: true });
479
+ }
424
480
  }
425
481
 
426
482
  function codexPluginManifest(opts) {
@@ -492,7 +548,7 @@ function codexPluginMcp(opts) {
492
548
  mcpServers: {
493
549
  sellable: {
494
550
  type: "stdio",
495
- command: "npx",
551
+ command: packageRunnerCommand(),
496
552
  args: ["-y", opts.mcpPackage],
497
553
  env: {
498
554
  SELLABLE_WATCH_MODE_DRIVER: "codex",
@@ -608,8 +664,8 @@ instruction loading, file lookup, plugin cache versions, missing linked files,
608
664
  or tool discovery. Start in product language:
609
665
 
610
666
  \`\`\`text
611
- I’ll help you launch this as a Sellable campaign. First I’ll resolve the
612
- client/company this campaign is for, then I’ll turn that into a campaign brief
667
+ I’ll help you launch this as a Sellable campaign. First I’ll research the
668
+ person/company this campaign is for, then I’ll turn that into a campaign brief
613
669
  before anything is created.
614
670
  \`\`\`
615
671
 
@@ -655,10 +711,12 @@ should say:
655
711
  - that approval authorizes scouting/search only, not lead import or sending
656
712
 
657
713
  Do not surface blanket source heuristics as product copy. Make the
658
- recommendation specific to the campaign. If Signal Discovery is recommended,
659
- name the exact post themes you will search. If relevant public conversations
660
- look unlikely, recommend the specific Sales Nav or Prospeo lane instead and say
661
- why. Do not call \`search_signals\`, \`search_sales_nav\`, \`search_prospeo\`,
714
+ recommendation specific to the campaign. If LinkedIn engagement is recommended,
715
+ name the exact post themes you will search and avoid using "Signal Discovery" in
716
+ customer-facing chat; that is the internal provider/app label. If relevant
717
+ public conversations look unlikely, recommend the specific Sales Nav or Prospeo
718
+ lane instead and say why. Do not call \`search_signals\`, \`search_sales_nav\`,
719
+ \`search_prospeo\`,
662
720
  \`fetch_post_engagers\`, or provider-scoped subagents until the user approves this
663
721
  source plan or explicitly chooses a different source.
664
722
 
@@ -677,9 +735,12 @@ precision, and referral paths, but it does not provide hiring-by-role filters;
677
735
  say that distinction plainly in the source-plan gate.
678
736
 
679
737
  After scouting, ask for a second approval on the concrete source action. For
680
- Signal Discovery, name how many selected posts will be scraped, the target
681
- engager/source-candidate volume, and the internal campaign-table execution-slice
682
- size. For Sales Nav or Prospeo, name the specific approved import lane and source lead count.
738
+ LinkedIn engagement (\`signal-discovery\` internally), name how many recommended
739
+ posts will be scraped, the target engager/source-candidate volume, and the
740
+ internal campaign-table execution-slice size. N must be the smallest
741
+ right-content post set that clears the source target, not the default 3
742
+ promoted sample posts. For Sales Nav or Prospeo, name the specific approved
743
+ import lane and source lead count.
683
744
  Do not call \`import_leads\` or \`confirm_lead_list\` until this second approval is
684
745
  granted.
685
746
 
@@ -838,10 +899,10 @@ customer-facing progress copy.
838
899
 
839
900
  Do not treat the active Sellable workspace as the campaign subject. The
840
901
  workspace only tells you where the campaign will be saved. Before buyer, CTA,
841
- proof, or source questions, identify the campaign identity: the person/profile
842
- or company this campaign is for, plus enough company/product context to build
843
- the brief. This is only the client-prospect/bootstrap identity for
844
- \`clientProspectId\` or \`senderLinkedinUrl\`; it is not a connected-sender check.
902
+ proof, or source questions, identify the person/profile or company this
903
+ campaign is for, plus enough current company/product context to build the
904
+ brief. This client/company lookup feeds \`clientProspectId\` or
905
+ \`senderLinkedinUrl\`; it is not a connected-sender check.
845
906
 
846
907
  Do not call \`mcp__sellable__list_senders\`, \`mcp__sellable__get_sender\`, or
847
908
  surface connected/missing sender state during setup, brief, source, filter, or
@@ -865,19 +926,20 @@ first:
865
926
  only if a URL/domain is also available.
866
927
 
867
928
  Then summarize what you found in one or two lines and ask the user to confirm
868
- the campaign identity/focus before continuing. Do not mention connected sender
869
- availability in this confirmation.
929
+ the current company/focus before continuing, especially if public website data
930
+ may be stale. Do not mention connected sender availability in this confirmation.
870
931
 
871
932
  If the user did not provide the launch identity, ask in normal chat for the
872
- LinkedIn profile or company website to use as the campaign identity. Do not ask
933
+ LinkedIn profile URL first, with the company website as the fallback. Do not ask
873
934
  them to choose an input type with the structured question tool:
874
935
 
875
936
  \`\`\`text
876
937
  I’m ready to build this in {workspace}.
877
938
 
878
- First, paste the LinkedIn profile or company website for the client/company this
879
- campaign is for. I’ll use that to resolve the campaign identity before we pick
880
- the target, offer, proof, and lead source.
939
+ What is your LinkedIn profile URL? If you do not have it handy, send your
940
+ company website instead. I’ll research the person and company from that, then
941
+ ask you to correct anything stale before we pick the target, offer, proof, and
942
+ lead source.
881
943
  \`\`\`
882
944
 
883
945
  After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn
@@ -887,18 +949,28 @@ most recent company from the profile. For a company website, call
887
949
  LinkedIn profile URL is available, retain it as \`senderLinkedinUrl\` for
888
950
  \`create_campaign\`; if a \`clientProspectId\` is available, pass that instead.
889
951
 
890
- After the user confirms the campaign identity, run one lightweight company
891
- lookup if it has not already run, then ask the campaign setup questions. The
892
- setup questions should use the confirmed company context so they do not feel
893
- generic.
952
+ After the user confirms the company/focus, run one lightweight company lookup
953
+ if it has not already run, then ask an offer-readiness question before inferred
954
+ strategy hardens:
955
+
956
+ \`\`\`text
957
+ Do you already know the offer for this campaign, should I use the researched
958
+ recommendation, or should we shape the offer together? If the website is stale,
959
+ tell me what is current before I build the brief.
960
+ \`\`\`
961
+
962
+ The setup questions should use the confirmed company context so they do not feel
963
+ generic. When you present a recommendation, introduce it as based on the
964
+ research you just did and keep it editable.
894
965
 
895
966
  Before the identity gate, use this customer-facing shape:
896
967
 
897
968
  \`\`\`text
898
969
  I’m ready to build the campaign in {workspace}.
899
970
 
900
- First I’ll resolve the client/company this campaign is for. I’ll use that
901
- context to choose the target, offer, proof, and lead source.
971
+ First I’ll research the person/company this campaign is for. I’ll use that
972
+ context to recommend a target, offer, proof, and lead source, then you can
973
+ correct anything stale before I build from it.
902
974
 
903
975
  Then I’ll turn that into a campaign brief for you to approve before anything is created.
904
976
  \`\`\`
@@ -1266,17 +1338,17 @@ show you the draft next so you can approve it or change it.
1266
1338
  Good opening:
1267
1339
 
1268
1340
  \`\`\`text
1269
- I’ll help you launch this as a Sellable campaign. First I’ll resolve the
1270
- client/company this campaign is for, then I’ll turn that into a campaign brief
1271
- before any leads are imported or anything can send.
1341
+ I’ll help you launch this as a Sellable campaign. First I’ll research the
1342
+ person/company this is for, then I’ll turn that into a campaign brief before
1343
+ any leads are imported or anything can send.
1272
1344
  \`\`\`
1273
1345
 
1274
1346
  Good identity setup:
1275
1347
 
1276
1348
  \`\`\`text
1277
- I’ll confirm the client/company this campaign is for before we pick the target,
1278
- offer, proof, and lead source. Paste a LinkedIn profile or company website and
1279
- I’ll resolve the campaign identity before the setup choices.
1349
+ I’ll ask for the LinkedIn profile URL first, with the company website as a
1350
+ fallback. Then I’ll show the researched recommendation and you can correct
1351
+ anything stale before we pick the target, offer, proof, and lead source.
1280
1352
  \`\`\`
1281
1353
 
1282
1354
  Bad:
@@ -1767,7 +1839,7 @@ function withWatchModeDriver(command, args, driver) {
1767
1839
 
1768
1840
  function mcpCommand(opts) {
1769
1841
  if (opts.server === "package") {
1770
- return ["npx", ["-y", opts.mcpPackage]];
1842
+ return [packageRunnerCommand(), ["-y", opts.mcpPackage]];
1771
1843
  }
1772
1844
  if (opts.server === "local") {
1773
1845
  if (!opts.localCommand) {
@@ -1789,6 +1861,33 @@ function mcpCommandForHost(opts, driver) {
1789
1861
  return withWatchModeDriver(command, args, driver);
1790
1862
  }
1791
1863
 
1864
+ function codexMcpAddArgs(opts) {
1865
+ const [command, args] = mcpCommand(opts);
1866
+ if (command === "hosted") {
1867
+ return ["mcp", "add", "sellable", "--url", args[0]];
1868
+ }
1869
+
1870
+ if (isWindowsPlatform()) {
1871
+ return [
1872
+ "mcp",
1873
+ "add",
1874
+ "sellable",
1875
+ "--env",
1876
+ WATCH_MODE_DRIVER_ENV.codex,
1877
+ "--",
1878
+ command,
1879
+ ...args,
1880
+ ];
1881
+ }
1882
+
1883
+ const [wrappedCommand, wrappedArgs] = withWatchModeDriver(
1884
+ command,
1885
+ args,
1886
+ "codex"
1887
+ );
1888
+ return ["mcp", "add", "sellable", "--", wrappedCommand, ...wrappedArgs];
1889
+ }
1890
+
1792
1891
  function installClaude(opts) {
1793
1892
  if (!commandExists("claude")) {
1794
1893
  const message =
@@ -1887,17 +1986,16 @@ function installCodex(opts) {
1887
1986
  throw new Error(message);
1888
1987
  }
1889
1988
  if (opts.server === "hosted") {
1890
- run("codex", ["mcp", "add", "sellable", "--url", opts.hostedUrl], opts);
1989
+ run("codex", codexMcpAddArgs(opts), opts);
1891
1990
  const info = installCodexDesktopPlugin(opts);
1892
1991
  return { installed: true, ...info };
1893
1992
  }
1894
- const [command, args] = mcpCommandForHost(opts, "codex");
1895
1993
  run("codex", ["mcp", "remove", "sellable"], {
1896
1994
  ...opts,
1897
1995
  dryRun: opts.dryRun,
1898
1996
  allowFail: true,
1899
1997
  });
1900
- run("codex", ["mcp", "add", "sellable", "--", command, ...args], opts);
1998
+ run("codex", codexMcpAddArgs(opts), opts);
1901
1999
  const info = installCodexDesktopPlugin(opts);
1902
2000
  return { installed: true, ...info };
1903
2001
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sellable/install",
3
- "version": "0.1.120",
3
+ "version": "0.1.122",
4
4
  "type": "module",
5
5
  "description": "One-command installer for Sellable MCP in Claude Code and Codex",
6
6
  "bin": {
@@ -86,8 +86,8 @@ instruction loading, file lookup, plugin cache versions, missing linked files,
86
86
  or tool discovery. Start in product language:
87
87
 
88
88
  ```text
89
- I’ll help you launch this as a Sellable campaign. First I’ll resolve the
90
- client/company this campaign is for, then I’ll turn that into a campaign brief
89
+ I’ll help you launch this as a Sellable campaign. First I’ll research the
90
+ person/company this campaign is for, then I’ll turn that into a campaign brief
91
91
  before we move into lead sourcing.
92
92
  ```
93
93
 
@@ -139,10 +139,12 @@ should say:
139
139
  - what approval covers in one concise line
140
140
 
141
141
  Do not surface blanket source heuristics as product copy. Make the
142
- recommendation specific to the campaign. If Signal Discovery is recommended,
143
- name the exact post themes you will search. If relevant public conversations
144
- look unlikely, recommend the specific Sales Nav or Prospeo lane instead and say
145
- why. Do not call `search_signals`, `search_sales_nav`, `search_prospeo`,
142
+ recommendation specific to the campaign. If LinkedIn engagement is recommended,
143
+ name the exact post themes you will search and avoid using "Signal Discovery" in
144
+ customer-facing chat; that is the internal provider/app label. If relevant
145
+ public conversations look unlikely, recommend the specific Sales Nav or Prospeo
146
+ lane instead and say why. Do not call `search_signals`, `search_sales_nav`,
147
+ `search_prospeo`,
146
148
  `fetch_post_engagers`, or provider-scoped subagents until the user approves this
147
149
  source plan or explicitly chooses a different source.
148
150
 
@@ -161,10 +163,13 @@ precision, and referral paths, but it does not provide hiring-by-role filters;
161
163
  say that distinction plainly in the source-plan gate.
162
164
 
163
165
  After scouting, ask for a second approval on the concrete source action. For
164
- Signal Discovery, name how many selected posts will be scraped and the
165
- target engager/source-candidate volume. For Sales Nav or Prospeo, name the
166
- specific approved import lane and source lead count. Keep the internal
167
- 15-row campaign-table execution slice separate from source sampling.
166
+ LinkedIn engagement (`signal-discovery` internally), name how many
167
+ recommended posts will be scraped and the target engager/source-candidate
168
+ volume. N must be the smallest right-content post set that clears the source
169
+ target, not the default 3 promoted sample posts. For Sales Nav or Prospeo,
170
+ name the specific approved import lane and source lead count. Keep the
171
+ internal 15-row campaign-table execution slice separate from source
172
+ sampling.
168
173
 
169
174
  Do not call `import_leads` or `confirm_lead_list` until this second approval is
170
175
  granted.
@@ -181,16 +186,15 @@ granted.
181
186
  should `confirm_lead_list({ reviewBatchLimit: 15 })` copy confirmed rows into
182
187
  the campaign table and return the initial campaign-table execution slice rows.
183
188
 
184
- For Signal Discovery, the customer-facing approval card must use the exact
185
- action shape "Approve scraping N Signal Discovery posts?" and the chat summary
186
- should be a compact `## Source Recommendation` block with:
189
+ For LinkedIn engagement, the customer-facing approval card must use the exact
190
+ action shape "Approve scraping N recommended LinkedIn posts?" and the chat
191
+ summary should be a compact `## Source Recommendation` block with:
187
192
 
188
- - goal: about 300 headline-fit prospects that pass the Signal Discovery
189
- headline criteria for now
193
+ - goal: about 300 headline-fit prospects from relevant LinkedIn engagement
190
194
  - source-candidate plan: use sample math first: target headline-fit prospects
191
195
  divided by sampled headline-pass rate. If there is no stronger sample, use
192
196
  about 1,500 raw engagers from the 20% working headline-pass assumption.
193
- - planning floor: continue with Signal Discovery only when sampled/projected
197
+ - planning floor: continue with LinkedIn engagement only when sampled/projected
194
198
  headline-fit rate is at least 10%; below that, move to Sales Nav recent
195
199
  activity instead of scraping noisy engagers. Do not use the 10% floor as the
196
200
  scrape-count denominator when the actual sample rate is higher.
@@ -394,10 +398,10 @@ customer-facing progress copy.
394
398
 
395
399
  Do not treat the active Sellable workspace as the campaign subject. The
396
400
  workspace only tells you where the campaign will be saved. Before buyer, CTA,
397
- proof, or source questions, identify the campaign identity: the person/profile
398
- or company this campaign is for, plus enough company/product context to build
399
- the brief. This is only the client-prospect/bootstrap identity for
400
- `clientProspectId` or `senderLinkedinUrl`; it is not a connected-sender check.
401
+ proof, or source questions, identify the person/profile or company this
402
+ campaign is for, plus enough current company/product context to build the
403
+ brief. This client/company lookup feeds `clientProspectId` or
404
+ `senderLinkedinUrl`; it is not a connected-sender check.
401
405
 
402
406
  Do not call `mcp__sellable__list_senders`, `mcp__sellable__get_sender`, or
403
407
  surface connected/missing sender state during setup, brief, source, filter, or
@@ -421,19 +425,20 @@ first:
421
425
  only if a URL/domain is also available.
422
426
 
423
427
  Then summarize what you found in one or two lines and ask the user to confirm
424
- the campaign identity/focus before continuing. Do not mention connected sender
425
- availability in this confirmation.
428
+ the current company/focus before continuing, especially if public website data
429
+ may be stale. Do not mention connected sender availability in this confirmation.
426
430
 
427
431
  If the user did not provide the launch identity, ask in normal chat for the
428
- LinkedIn profile or company website to use as the campaign identity. Do not ask
432
+ LinkedIn profile URL first, with the company website as the fallback. Do not ask
429
433
  them to choose an input type with the structured question tool:
430
434
 
431
435
  ```text
432
436
  I’m ready to build this in {workspace}.
433
437
 
434
- First, paste the LinkedIn profile or company website for the client/company this
435
- campaign is for. I’ll use that to resolve the campaign identity before we pick
436
- the target, offer, proof, and lead source.
438
+ What is your LinkedIn profile URL? If you do not have it handy, send your
439
+ company website instead. I’ll research the person and company from that, then
440
+ ask you to correct anything stale before we pick the target, offer, proof, and
441
+ lead source.
437
442
  ```
438
443
 
439
444
  After the user pastes a URL/domain, do the lightweight lookup. For a LinkedIn
@@ -443,10 +448,19 @@ most recent company from the profile. For a company website, call
443
448
  LinkedIn profile URL is available, retain it as `senderLinkedinUrl` for
444
449
  `create_campaign`; if a `clientProspectId` is available, pass that instead.
445
450
 
446
- After the user confirms the campaign identity, run one lightweight company
447
- lookup if it has not already run, then ask the campaign setup questions. The
448
- setup questions should use the confirmed company context so they do not feel
449
- generic.
451
+ After the user confirms the company/focus, run one lightweight company lookup
452
+ if it has not already run, then ask an offer-readiness question before inferred
453
+ strategy hardens:
454
+
455
+ ```text
456
+ Do you already know the offer for this campaign, should I use the researched
457
+ recommendation, or should we shape the offer together? If the website is stale,
458
+ tell me what is current before I build the brief.
459
+ ```
460
+
461
+ The setup questions should use the confirmed company context so they do not feel
462
+ generic. When you present a recommendation, introduce it as based on the
463
+ research you just did and keep it editable.
450
464
 
451
465
  ### Sufficient Intake Bypass
452
466
 
@@ -474,9 +488,9 @@ If the invocation or any later user message explicitly asks for "yolo mode",
474
488
  me", "use best estimates", or "just run it", enable YOLO mode for the rest of
475
489
  the run. Treat YOLO as `interactionMode: "autonomous"` plus an intake policy:
476
490
 
477
- - If campaign identity is missing, ask only for the LinkedIn profile or company
478
- website in normal chat; do not ask buyer, offer, proof, source, or filter setup
479
- questions before that.
491
+ - If the campaign subject is missing, ask only for the LinkedIn profile URL
492
+ first, with company website as the fallback, in normal chat; do not ask buyer,
493
+ offer, proof, source, or filter setup questions before that.
480
494
  - Treat any freeform directions already provided, or added later by the user, as
481
495
  operator directions for the rest of the run. If directions conflict, the newest
482
496
  user direction wins.
@@ -498,8 +512,9 @@ Before the identity gate, use this customer-facing shape:
498
512
  ```text
499
513
  I’m ready to build the campaign in {workspace}.
500
514
 
501
- First I’ll resolve the client/company this campaign is for. I’ll use that
502
- context to choose the target, offer, proof, and lead source.
515
+ First I’ll research the person/company this campaign is for. I’ll use that
516
+ context to recommend a target, offer, proof, and lead source, then you can
517
+ correct anything stale before I build from it.
503
518
 
504
519
  Then I’ll turn that into a campaign brief for you to approve before any leads
505
520
  are sourced.
@@ -634,9 +649,9 @@ updates.
634
649
  ```text
635
650
  You're in — {activeWorkspaceName} workspace, ready to roll.
636
651
 
637
- Now — paste the LinkedIn profile or company website for the client/company this campaign is for. I’ll use that to resolve the campaign identity before we pick the target, offer, proof, and lead source.
652
+ Now — what is your LinkedIn profile URL? If you do not have it handy, send your company website instead. I’ll research the person and company from that, then ask you to correct anything stale before we pick the target, offer, proof, and lead source.
638
653
 
639
- e.g. https://example.com or https://www.linkedin.com/in/client-handle
654
+ e.g. https://www.linkedin.com/in/client-handle or https://example.com
640
655
  ```
641
656
 
642
657
  - If `isReturningUser === false`, prepend ONE line confirming the new
@@ -645,9 +660,9 @@ updates.
645
660
  ```text
646
661
  You're set up — your {activeWorkspaceName} workspace is ready.
647
662
 
648
- Now — paste the LinkedIn profile or company website for the client/company this campaign is for. I’ll use that to resolve the campaign identity before we pick the target, offer, proof, and lead source.
663
+ Now — what is your LinkedIn profile URL? If you do not have it handy, send your company website instead. I’ll research the person and company from that, then ask you to correct anything stale before we pick the target, offer, proof, and lead source.
649
664
 
650
- e.g. https://example.com or https://www.linkedin.com/in/client-handle
665
+ e.g. https://www.linkedin.com/in/client-handle or https://example.com
651
666
  ```
652
667
 
653
668
  No other lines. No "all set", no "signed in", no other acknowledgement.