marketing-mindset 1.7.0 → 1.8.0
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 +20 -0
- package/bin/cli.js +59 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -94,3 +94,23 @@ the dated read, a week-by-week table with the percentage of the floor covered, t
|
|
|
94
94
|
kill rule. `--json` returns the same object for an agent or a script.
|
|
95
95
|
|
|
96
96
|
Method, packages and the paid version of this work: https://axelfreeman.com/marketing-engineer.html
|
|
97
|
+
|
|
98
|
+
## `mde` — what a volume you can afford can actually read
|
|
99
|
+
|
|
100
|
+
The other direction of the same arithmetic: instead of the volume a lift requires, the lift a volume can
|
|
101
|
+
read. Useful when the channel caps the volume (a small list, a niche audience, one store's traffic) and the
|
|
102
|
+
honest question is not "how much do we need" but "what is the smallest win this test could ever show".
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
npx marketing-mindset mde --base 0.03 --per-arm 5000
|
|
106
|
+
# base rate 3.00% · per arm 5,000 · power 0.8 · alpha 0.05
|
|
107
|
+
# smallest readable relative lift: 33.4% (1pp absolute)
|
|
108
|
+
# verdict: at this volume only a difference of 33.4% or more is readable ...
|
|
109
|
+
|
|
110
|
+
npx marketing-mindset mde --base 0.03 --per-arm 5000 --json
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`--per-arm` takes the volume you can actually buy per variant; `--power` (0.8 or 0.9) and `--alpha`
|
|
114
|
+
(0.05, 0.01, 0.1) are the same knobs as `sample`. When no lift is readable at that volume the command
|
|
115
|
+
says so instead of printing a number, and names the three ways out: more volume, a higher base rate, or a
|
|
116
|
+
cheaper measurable unit (for cold email the reply rate, floor ~1,500–2,000 sends per variant).
|
package/bin/cli.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* marketing-mindset help + the test-size floors
|
|
4
4
|
* marketing-mindset sample required per-arm sample size for a two-proportion test
|
|
5
5
|
* marketing-mindset kill the kill rule for a running test
|
|
6
|
+
* marketing-mindset mde smallest relative lift a fixed per-arm volume can read
|
|
6
7
|
* marketing-mindset sections list every section of SKILL.md
|
|
7
8
|
* marketing-mindset read <text> print one section by fuzzy title match
|
|
8
9
|
* marketing-mindset install copy the skill into your agent's skills directory
|
|
@@ -383,6 +384,60 @@ function runPlan(opts) {
|
|
|
383
384
|
|
|
384
385
|
/* brief — the whole plan as one markdown page a client can keep: the floor, what reaching it costs,
|
|
385
386
|
* the dates, the gate for each week and the kill rule. --json returns the same object for an agent. */
|
|
387
|
+
function mdeLift(rate, perArm, power, alpha) {
|
|
388
|
+
if (sampleSize(rate, 5, power, alpha) > perArm) { return null; }
|
|
389
|
+
let lo = 1e-6, hi = 5;
|
|
390
|
+
for (let i = 0; i < 100; i++) {
|
|
391
|
+
const mid = (lo + hi) / 2;
|
|
392
|
+
if (sampleSize(rate, mid, power, alpha) <= perArm) { hi = mid; } else { lo = mid; }
|
|
393
|
+
}
|
|
394
|
+
return hi;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function runMde(opts) {
|
|
398
|
+
const rate = Number(opts.base !== undefined ? opts.base : 0.03);
|
|
399
|
+
const perArm = Number(opts["per-arm"] !== undefined ? opts["per-arm"] : (opts.n !== undefined ? opts.n : 5000));
|
|
400
|
+
const power = Number(opts.power !== undefined ? opts.power : 0.8);
|
|
401
|
+
const alpha = Number(opts.alpha !== undefined ? opts.alpha : 0.05);
|
|
402
|
+
const problems = [];
|
|
403
|
+
if (!(rate > 0 && rate < 1)) { problems.push("base must be between 0 and 1 (0.03 = 3%)"); }
|
|
404
|
+
if (!(perArm > 0)) { problems.push("per-arm must be a positive volume (contacts, sends or visitors)"); }
|
|
405
|
+
if (!ZB[String(power)]) { problems.push("power must be 0.8 or 0.9 - this CLI carries exact quantiles for those two"); }
|
|
406
|
+
if (!ZA[String(alpha)]) { problems.push("alpha must be 0.05, 0.01 or 0.1"); }
|
|
407
|
+
if (problems.length) { console.error("mde: " + problems.join("; ")); return 1; }
|
|
408
|
+
const lift = mdeLift(rate, perArm, power, alpha);
|
|
409
|
+
if (lift === null) {
|
|
410
|
+
const out = {
|
|
411
|
+
base_rate: rate, per_arm: perArm, power, alpha,
|
|
412
|
+
min_relative_lift: null, min_absolute_pp: null, readable: false,
|
|
413
|
+
verdict: "no lift is readable at this volume: even a five-fold difference needs more than " + fmtNum(perArm) + " per arm at a " + (rate * 100).toFixed(2) + "% base rate. Raise the volume, raise the base rate (tighter list or sharper promise), or measure a cheaper unit (for cold email the readable unit is the reply rate, floor ~1,500-2,000 sends per variant)."
|
|
414
|
+
};
|
|
415
|
+
if (opts.json) { console.log(JSON.stringify(out, null, 2)); } else {
|
|
416
|
+
console.log("base rate " + (rate * 100).toFixed(2) + "% · per arm " + fmtNum(perArm) + " · power " + power + " · alpha " + alpha);
|
|
417
|
+
console.log("smallest readable relative lift: none");
|
|
418
|
+
console.log("verdict: " + out.verdict);
|
|
419
|
+
}
|
|
420
|
+
return 0;
|
|
421
|
+
}
|
|
422
|
+
const pct = Math.round(lift * 1000) / 10;
|
|
423
|
+
const pp = Math.round(rate * lift * 100 * 100) / 100;
|
|
424
|
+
const verdict = pct >= 20
|
|
425
|
+
? "at this volume only a difference of " + pct + "% or more is readable - a smaller win will not separate from noise, so the honest plan is a bigger volume before the first read"
|
|
426
|
+
: "at this volume a difference of " + pct + "% or more is readable - a plan that promises less than that is promising a number this test cannot produce";
|
|
427
|
+
const out = {
|
|
428
|
+
base_rate: rate, per_arm: perArm, power, alpha,
|
|
429
|
+
min_relative_lift: Math.round(lift * 1e9) / 1e9,
|
|
430
|
+
min_absolute_pp: pp, readable: true, verdict
|
|
431
|
+
};
|
|
432
|
+
if (opts.json) { console.log(JSON.stringify(out, null, 2)); } else {
|
|
433
|
+
console.log("base rate " + (rate * 100).toFixed(2) + "% · per arm " + fmtNum(perArm) + " · power " + power + " · alpha " + alpha);
|
|
434
|
+
console.log("smallest readable relative lift: " + pct + "% (" + pp + "pp absolute)");
|
|
435
|
+
console.log("contacts needed at that lift: " + fmtNum(sampleSize(rate, lift, power, alpha)) + " per arm");
|
|
436
|
+
console.log("verdict: " + verdict);
|
|
437
|
+
}
|
|
438
|
+
return 0;
|
|
439
|
+
}
|
|
440
|
+
|
|
386
441
|
function fmtNum(n) {
|
|
387
442
|
return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
388
443
|
}
|
|
@@ -519,6 +574,8 @@ if (cmd === "sample") {
|
|
|
519
574
|
process.exit(runBrief(flags(rest)));
|
|
520
575
|
} else if (cmd === "plan") {
|
|
521
576
|
process.exit(runPlan(flags(rest)));
|
|
577
|
+
} else if (cmd === "mde") {
|
|
578
|
+
process.exit(runMde(flags(rest)));
|
|
522
579
|
} else if (cmd === "budget") {
|
|
523
580
|
process.exit(runBudget(flags(rest)));
|
|
524
581
|
} else if (cmd === "warmup") {
|
|
@@ -553,6 +610,8 @@ Usage:
|
|
|
553
610
|
--base 0.03 --lift 0.2 --cpl 4 [--daily 500]
|
|
554
611
|
npx marketing-mindset plan dated plan: weekly volume, gates, first honest read
|
|
555
612
|
--base 0.03 --lift 0.2 --daily 500 [--weeks 4] [--start 2026-09-21]
|
|
613
|
+
npx marketing-mindset mde what a volume you can afford can actually read
|
|
614
|
+
--base 0.03 --per-arm 5000 [--power 0.8] [--alpha 0.05] [--json]
|
|
556
615
|
npx marketing-mindset warmup day-by-day sending ramp with stop rules
|
|
557
616
|
--start 2026-09-21 --target 200 --days 21 --mailboxes 4
|
|
558
617
|
npx marketing-mindset jd marketing engineer job description
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "marketing-mindset",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "A marketer's operating mindset as an installable agent skill and CLI: test-size floors, kill rules, agent-readiness checklist, marketing-engineer job description. npx marketing-mindset sample|kill|budget|brief|plan|warmup|aeo|jd|sections|read|install.",
|
|
3
|
+
"version": "1.8.0",
|
|
4
|
+
"description": "A marketer's operating mindset as an installable agent skill and CLI: test-size floors, kill rules, the lift a volume can actually read, agent-readiness checklist, marketing-engineer job description. npx marketing-mindset sample|kill|mde|budget|brief|plan|warmup|aeo|jd|sections|read|install.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-skill",
|
|
7
7
|
"skill",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"llm",
|
|
14
14
|
"prompt",
|
|
15
15
|
"sample-size",
|
|
16
|
+
"minimum-detectable-effect",
|
|
16
17
|
"job-description",
|
|
17
18
|
"cold-email",
|
|
18
19
|
"deliverability",
|