@wrangled/cli 0.3.167 → 0.3.168

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/dist/guide.js CHANGED
@@ -120,7 +120,7 @@ The \`weekly-loop\` playbook (\`${cli} skill install weekly-loop\` installs it a
120
120
 
121
121
  A test writes down one change to a page or funnel step, tried against what runs now. Each test is kept in the workspace's warehouse, in \`cro_tests\` (one row per test), \`cro_test_arms\` (its sides), \`cro_test_events\` (its history), \`cro_test_results_daily\` (each side's numbers per day) and \`cro_test_reported\` (numbers other tools counted), so you can join tests with visits, sign-ups and sales in one query: \`${cli} warehouse query "SELECT test_id, status, category, subcategory FROM cro_tests"\`.
122
122
 
123
- A test moves through these stages: \`idea\` (only the one change and where are needed), \`planned\` (the full plan is in and the owner said yes), \`running\` (its plan is frozen), then \`decided\`, \`abandoned\` or \`invalid\` (the tracking broke or traffic did not split as planned). Where is a funnel step (\`funnel_key\` and \`step_key\` from the funnels map), a page by its address (\`page_url\`, even one not on the map yet), or both. The full plan is: \`because\` (what led to the idea), \`audience\`, \`expected_lift\` (relative, 0.18 for 18%), \`prediction_confidence\` (low, medium or high), \`disproved_if\`, \`design_type\` (how traffic is split: ad_split_randomized, Meta's own A/B test; ad_split_duplicated, two copies of a campaign, one to each page, which is not a true random split; tool_split, inside a page builder or webinar tool named in a \`design_note\`; link_split; before_after; or adaptive), \`traffic\` (\`{campaigns, optimization_goal, note}\`: which campaigns feed it and what they optimize for, frozen with the plan), \`metric\` (step_conversion, which needs a step, sales_per_visitor, revenue_per_visitor, cost_per_sale or cost_per_lead, spend per sign-up) and \`unit\` (people or sessions), \`guardrails\` (numbers that must not get worse), \`baseline_rate\` with \`baseline_from\` and \`baseline_to\`, \`min_lift\`, \`people_per_arm\`, \`min_days\` and \`max_days\` (14 and 56 unless set), \`decision_rule\`, \`concurrent_changes\`, and the control and 1 to 3 \`variants\`, each with the exact \`content\` it shows and, when a tool runs the split, its \`platform_ref\` (the tool's own id for the side). What a test is mainly about is a \`category\` and its \`subcategory\`, from a fixed list: copy (headline, subheadline, body, call_to_action, bullets, story, other), offer (price, bonus, guarantee, payment_plan, order_bump, upsell, deadline_or_scarcity, other), proof (testimonials, case_study, numbers_and_results, logos_or_press, reviews, other), design (layout, hero_image, video, colors, page_length, mobile, other), form_checkout (form_fields, number_of_steps, checkout_page, other), webinar_event (length, presenter, offer_timing, replay, reminders, other), follow_up (email, text_message, thank_you_page, other), audience_traffic (who_sees_it, ad_angle, optimization_goal, other), tool_platform (webinar_platform, page_builder, checkout_tool, other), and custom, which has no subcategory. Subcategory \`other\` and category \`custom\` need a \`label\` naming what was tested, such as "exit pop-up", kept in lower case. \`also_changed\` lists anything else the test changed, each \`copy.subheadline\`, \`offer.other:<label>\` or \`custom:<label>\`. \`${cli} tests categories\` prints the list and the labels this workspace already uses: reuse one that fits before writing a new one. \`${cli} tests draft\` and \`${cli} tests edit\` take them as flags too: \`--category copy --subcategory headline --also copy.subheadline\`. \`levers\` tag why it should work, from a fixed list: clarity, relevance, trust, value, urgency, less_effort, motivation, other. \`ice_impact\`, \`ice_confidence\` and \`ice_ease\` (1 to 10) sort the idea list. \`evidence\` quotes the proof, each \`{kind, ref, note}\`, kind one of leak, lesson, customer_words, page, ad or other. A test changes one thing: a \`change\` naming two is refused.
123
+ A test moves through these stages: \`idea\` (only the one change and where are needed), \`planned\` (the full plan is in and the owner said yes), \`running\` (its plan is frozen), then \`decided\`, \`abandoned\` or \`invalid\` (the tracking broke or traffic did not split as planned). Where is a funnel step (\`funnel_key\` and \`step_key\` from the funnels map), a page by its address (\`page_url\`, even one not on the map yet), or both. The full plan is: \`because\` (what led to the idea), \`audience\`, \`expected_lift\` (relative, 0.18 for 18%), \`prediction_confidence\` (low, medium or high), \`disproved_if\`, \`design_type\` (how traffic is split: ad_split_randomized, Meta's own A/B test; ad_split_duplicated, two copies of a campaign, one to each page, which is not a true random split; tool_split, inside a page builder or webinar tool named in a \`design_note\`; link_split; before_after; or adaptive), \`traffic\` (\`{campaigns, optimization_goal, note}\`: which campaigns feed it and what they optimize for, frozen with the plan), \`metric\` (step_conversion, which needs a step, sales_per_visitor, revenue_per_visitor, cost_per_sale or cost_per_lead, spend per sign-up) and \`unit\` (people or sessions), \`guardrails\` (numbers that must not get worse), \`baseline_rate\` with \`baseline_from\` and \`baseline_to\`, \`min_lift\`, \`people_per_arm\`, \`min_days\` and \`max_days\` (14 and 56 unless set), \`decision_rule\`, \`concurrent_changes\`, and the control and 1 to 3 \`variants\`, each with the exact \`content\` it shows and, when a tool runs the split, its \`platform_ref\` (the tool's own id for the side). A page builder that serves every side at one address (ClickFunnels' first step, Unbounce) is counted from the site's own visits when each side gives the \`version_label\` its page declares through the visit tag (\`data-${brand.slug}-version\`) and the shared \`page\` or \`url\`; a visitor who saw two versions counts on neither side. GoHighLevel sends each side to its own path, so each side's \`url\` is enough. What a test is mainly about is a \`category\` and its \`subcategory\`, from a fixed list: copy (headline, subheadline, body, call_to_action, bullets, story, other), offer (price, bonus, guarantee, payment_plan, order_bump, upsell, deadline_or_scarcity, other), proof (testimonials, case_study, numbers_and_results, logos_or_press, reviews, other), design (layout, hero_image, video, colors, page_length, mobile, other), form_checkout (form_fields, number_of_steps, checkout_page, other), webinar_event (length, presenter, offer_timing, replay, reminders, other), follow_up (email, text_message, thank_you_page, other), audience_traffic (who_sees_it, ad_angle, optimization_goal, other), tool_platform (webinar_platform, page_builder, checkout_tool, other), and custom, which has no subcategory. Subcategory \`other\` and category \`custom\` need a \`label\` naming what was tested, such as "exit pop-up", kept in lower case. \`also_changed\` lists anything else the test changed, each \`copy.subheadline\`, \`offer.other:<label>\` or \`custom:<label>\`. \`${cli} tests categories\` prints the list and the labels this workspace already uses: reuse one that fits before writing a new one. \`${cli} tests draft\` and \`${cli} tests edit\` take them as flags too: \`--category copy --subcategory headline --also copy.subheadline\`. \`levers\` tag why it should work, from a fixed list: clarity, relevance, trust, value, urgency, less_effort, motivation, other. \`ice_impact\`, \`ice_confidence\` and \`ice_ease\` (1 to 10) sort the idea list. \`evidence\` quotes the proof, each \`{kind, ref, note}\`, kind one of leak, lesson, customer_words, page, ad or other. A test changes one thing: a \`change\` naming two is refused.
124
124
 
125
125
  Write it as JSON, such as \`${JSON.stringify(funnelTestExample)}\`, and run \`${cli} tests draft --file test.json\`. It gets Adzara-style labels from the change and this month (\`hyp-<slug>\` and \`test-<yyyy-mm>-<slug>\`); give \`hypothesis_id\` and \`test_id\` to reuse Adzara's own, so the results of the ads Adzara published for the test (\`ad_test_results_daily\`, \`ad_hypothesis_results_daily\`) join on the same label. \`${cli} tests edit <test_id> --file changes.json\` changes some fields (null clears one). ${brand.name} shows no approval screen: ask the owner in your own session, then record the yes with \`${cli} tests plan <test_id> --approved-by "<owner>"\`, which refuses a plan with a gap and names every missing field. \`${cli} tests start <test_id>\` marks a planned test as running from today and freezes its plan; an edit after that is still saved, and its history and results say so. Starting changes nothing live: the page still goes live through its own approval, and the ads through ${brand.name}'s Meta commands. Until #2202, an ad split test can be measured only on ads Adzara made before the switch, because its sides are counted from Adzara's labels; a \`before_after\` test still works. \`${cli} tests abandon <test_id> --note "<why>"\` drops one that has not ended, \`${cli} tests invalidate <test_id> --note "<what went wrong>"\` ends a running one whose numbers cannot be trusted, and \`${cli} tests note <test_id> --note "<note>"\` adds to its history. \`${cli} tests [--status <status>] [--funnel <funnel_key>] [--limit <n>]\` lists them, newest first (50 unless \`--limit\`, at most 200), and \`${cli} tests show <test_id>\` shows one with its history.
126
126
 
package/dist/main.js CHANGED
@@ -4855,6 +4855,7 @@ function printTest(t, events) {
4855
4855
  a.item_id && `item ${a.item_id}`,
4856
4856
  a.asset_version && `version ${a.asset_version}`,
4857
4857
  a.platform_ref && `tool id ${a.platform_ref}`,
4858
+ a.version_label && `version label ${a.version_label}`,
4858
4859
  a.weight !== null && `${Math.round(a.weight * 100)}% of traffic`,
4859
4860
  ]
4860
4861
  .filter(Boolean)
package/dist/playbooks.js CHANGED
@@ -2080,9 +2080,9 @@ ${JSON.stringify(croTestExample)}
2080
2080
  \`\`\`
2081
2081
 
2082
2082
  - \`change\` is the one change. \`because\` is what led to it, \`audience\` who sees it, \`expected_lift\` how much it should move (0.15 for 15%) and \`prediction_confidence\` how sure you are; \`disproved_if\` says what result would prove it wrong.
2083
- - \`control\` is what runs now; \`variants\` is the changed version, each \`{label, content, page?, url?, item_id?, asset_version?}\`. \`content\` is the exact words or change each side shows.
2083
+ - \`control\` is what runs now; \`variants\` is the changed version, each \`{label, content, page?, url?, item_id?, asset_version?, platform_ref?, version_label?}\`. \`content\` is the exact words or change each side shows.
2084
2084
  - \`metric\` is the number that should move: \`step_conversion\` (only with a \`step_key\`), \`sales_per_visitor\`, \`revenue_per_visitor\`, \`cost_per_sale\` or \`cost_per_lead\` (spend per sign-up), counted by \`unit\` (people or sessions). \`baseline_rate\` is today's rate over \`baseline_from\` to \`baseline_to\`, \`min_lift\` the smallest lift worth finding, \`people_per_arm\` how many each side needs, \`guardrails\` the numbers that must not get worse, and \`decision_rule\` how you will call it. \`min_days\` and \`max_days\` are 14 and 56 unless set.
2085
- - \`design_type\` is how traffic is split: \`ad_split_randomized\` (Meta's own A/B test), \`ad_split_duplicated\` (two copies of a campaign, one to each page; not a true random split), \`tool_split\` (inside a page builder or webinar tool, named in \`design_note\`), \`link_split\`, \`before_after\` or \`adaptive\`. \`traffic\` says which campaigns feed it and what they optimize for. Until #2202, an ad split test is counted only from Adzara's labels, so it can be measured only on ads Adzara made before the switch; for a new test, use \`before_after\`.
2085
+ - \`design_type\` is how traffic is split: \`ad_split_randomized\` (Meta's own A/B test), \`ad_split_duplicated\` (two copies of a campaign, one to each page; not a true random split), \`tool_split\` (inside a page builder or webinar tool, named in \`design_note\`; for GoHighLevel, which sends each side to its own path, give each side's \`url\`; for a builder that serves every side at one address, such as ClickFunnels' first step, give each side the shared \`url\` and the \`version_label\` its page declares with \`data-${cli}-version\`, and the visits count it), \`link_split\`, \`before_after\` or \`adaptive\`. \`traffic\` says which campaigns feed it and what they optimize for. Until #2202, an ad split test is counted only from Adzara's labels, so it can be measured only on ads Adzara made before the switch; for a new test, use \`before_after\`.
2086
2086
  - \`category\` and \`subcategory\` say what the test is mainly about, and \`also_changed\` anything else it changed: run \`${cli} tests categories\` for the lists and the labels already used, and reuse a label before writing a new one. \`levers\` tag why it should work, from \`${cli} guide\`'s fixed list.
2087
2087
  - \`evidence\` quotes the proof, each \`{kind, ref, note}\` with kind \`leak\`, \`lesson\`, \`customer_words\`, \`page\`, \`ad\` or \`other\`. Start with the leak itself.
2088
2088
  - Give \`hypothesis_id\` and \`test_id\` only to reuse Adzara's own labels; left out, they are made for you.
@@ -2140,7 +2140,7 @@ Without a shell: MCP \`get_funnel_test_results\` with \`{"id": "<test_id>"}\`.
2140
2140
  - **Every call is \`too_early\` or \`not_enough_yet\`:** leave the test running; that needs no command.
2141
2141
  - **A call is \`split_broken\`:** people did not split between the sides as planned. Tell the owner the result cannot be trusted, and suggest marking the test invalid (\`${cli} tests invalidate <test_id> --note "<what went wrong>"\`) once the split is checked.
2142
2142
  - **A call is directional:** it is a hunch, not a win. Suggest keeping the test running to its most days, or \`iterate\` to retest a sharper version; never \`scale\` on it. Only when something outside the test got in the way (the page broke, a price changed, the ads stopped), suggest \`hold\` to the owner.
2143
- - **The split runs in another tool** (a \`tool_split\` in GoHighLevel, a Meta A/B test): read each side's numbers in that tool and enter them with \`${cli} tests report <test_id> --file counts.json\` (MCP \`report_test_numbers\`), then read the results again; their words start "Counted by <tool>". Never decide a test judged on sales on Meta's purchase count alone.
2143
+ - **The split runs in another tool and no side was counted here** (a \`tool_split\` with no side's page or version label counted, a Meta A/B test): read each side's numbers in that tool and enter them with \`${cli} tests report <test_id> --file counts.json\` (MCP \`report_test_numbers\`), then read the results again; their words start "Counted by <tool>". Never decide a test judged on sales on Meta's purchase count alone.
2144
2144
  - **A call is ready** (a win, or no difference found): suggest \`scale\` (the new version won), \`stop\` (it lost or made no difference) or \`iterate\` (promising; it writes down a sharper version). \`iterate\` writes a new test, so suggest it only while the week is under its 3; otherwise suggest \`stop\` and draft the sharper version next week.
2145
2145
 
2146
2146
  Put each suggestion to the owner with the ideas from step 4, then record the owner's decision:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrangled/cli",
3
- "version": "0.3.167",
3
+ "version": "0.3.168",
4
4
  "description": "Command-line access to your marketing data warehouse, for people and coding agents",
5
5
  "type": "module",
6
6
  "bin": {