@koda-sl/baker-cli 0.131.0 → 0.132.0-dev.cad5e0bc7

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
@@ -223,8 +223,6 @@ baker ads google query --list-presets
223
223
  | `keyword-analysis` | Keyword performance with match type | LAST_30_DAYS |
224
224
  | `positive-keywords` | Positive (targeting) keywords only | ALL_TIME |
225
225
  | `negative-keywords` | Negative (blocking) keywords only | ALL_TIME |
226
- | `negative-keyword-lists` | Shared negative lists + their terms | ALL_TIME |
227
- | `negative-list-attachments`| Which campaigns each shared list covers | ALL_TIME |
228
226
  | `search-terms` | Actual user queries triggering ads | LAST_7_DAYS |
229
227
  | `ad-copy-performance` | Ad headline/description effectiveness | LAST_30_DAYS |
230
228
  | `asset-performance` | PMax asset performance labels | LAST_30_DAYS |
@@ -399,6 +397,262 @@ baker ads google keywords metrics --customer-id 1234567890 --keywords "running s
399
397
 
400
398
  ---
401
399
 
400
+ ### Google Ads Library (`baker ads google library`)
401
+
402
+ Manage and search the Google Ads Transparency Center. Track competitor advertisers, browse their ad creatives, and discover who's bidding on keywords.
403
+
404
+ **Typical workflow:** `search-advertiser` → `track` → `search-ads`
405
+
406
+ ---
407
+
408
+ ### `baker ads google library search-advertiser "query"`
409
+
410
+ Search for an advertiser on the Google Ads Transparency Center.
411
+
412
+ > **Recommended:** use the domain running the ads (e.g. `example.com`) for more accurate results.
413
+
414
+ ```bash
415
+ baker ads google library search-advertiser "example.com"
416
+ baker ads google library search-advertiser "Nike"
417
+ ```
418
+
419
+ **Response:**
420
+
421
+ ```json
422
+ {
423
+ "ok": true,
424
+ "data": {
425
+ "results": [
426
+ { "advertiserId": "AR12345678901234567", "name": "Nike, Inc.", "region": "US", "format": "TEXT_IMAGE_VIDEO" }
427
+ ]
428
+ }
429
+ }
430
+ ```
431
+
432
+ **Flags:**
433
+
434
+ | Flag | Description |
435
+ |------------|--------------------------------|
436
+ | `--output` | Format: `json` \| `csv` \| `md` |
437
+
438
+ ---
439
+
440
+ ### `baker ads google library track <id> <name>`
441
+
442
+ Track a new Google advertiser and wait for the initial ad sync to complete. Polls every 5 seconds with a 10-minute timeout. Progress is written to stderr.
443
+
444
+ ```bash
445
+ baker ads google library track AR12345678901234567 "Nike, Inc."
446
+ baker ads google library track AR12345678901234567 "Nike, Inc." --json
447
+ ```
448
+
449
+ **Response (with `--json`):**
450
+
451
+ ```json
452
+ {
453
+ "ok": true,
454
+ "data": {
455
+ "advertiserId": "ar_abc123",
456
+ "accountId": "acc_def456",
457
+ "totalAdCount": 342,
458
+ "activeAdCount": 89
459
+ }
460
+ }
461
+ ```
462
+
463
+ **Flags:**
464
+
465
+ | Flag | Description |
466
+ |----------|----------------------|
467
+ | `--json` | Output in JSON format |
468
+
469
+ ---
470
+
471
+ ### `baker ads google library list-advertisers`
472
+
473
+ List all tracked Google advertisers and their accounts.
474
+
475
+ ```bash
476
+ baker ads google library list-advertisers
477
+ baker ads google library list-advertisers --output md
478
+ ```
479
+
480
+ **Flags:**
481
+
482
+ | Flag | Description |
483
+ |------------|--------------------------------|
484
+ | `--output` | Format: `json` \| `csv` \| `md` |
485
+
486
+ ---
487
+
488
+ ### `baker ads google library sync-status <accountId>`
489
+
490
+ Check the sync status and ad counts of a tracked account.
491
+
492
+ ```bash
493
+ baker ads google library sync-status acc_def456
494
+ ```
495
+
496
+ **Response:**
497
+
498
+ ```json
499
+ {
500
+ "ok": true,
501
+ "data": {
502
+ "syncStatus": null,
503
+ "totalAdCount": 342,
504
+ "activeAdCount": 89
505
+ }
506
+ }
507
+ ```
508
+
509
+ `syncStatus` is `null` when idle, `"syncing"` during a sync, or `"error"` if the last sync failed.
510
+
511
+ ---
512
+
513
+ ### `baker ads google library search-ads <accountId>`
514
+
515
+ Search and filter ads for a tracked account. Supports pagination.
516
+
517
+ ```bash
518
+ baker ads google library search-ads acc_def456
519
+ baker ads google library search-ads acc_def456 --search "summer sale" --isActive --mediaType image
520
+ baker ads google library search-ads acc_def456 --sort newest --limit 50
521
+ baker ads google library search-ads acc_def456 --cursor "eyJwYWdl..."
522
+ ```
523
+
524
+ **Response:**
525
+
526
+ ```json
527
+ {
528
+ "ok": true,
529
+ "data": {
530
+ "page": [
531
+ {
532
+ "_id": "abc123",
533
+ "platform": "google",
534
+ "externalId": "CR_1234567890",
535
+ "isActive": true,
536
+ "mediaType": "image",
537
+ "headline": "Summer Sale — 50% Off Everything",
538
+ "description": "Shop our biggest sale of the year. Free shipping on all orders.",
539
+ "destinationUrl": "https://example.com/summer-sale",
540
+ "bodyText": "Summer Sale — 50% Off Everything",
541
+ "pageName": "Example Store",
542
+ "impressionsMin": 100000,
543
+ "impressionsMax": 200000,
544
+ "startDate": "2025-06-01",
545
+ "endDate": "2025-06-30",
546
+ "firstSeenAt": 1717200000000,
547
+ "lastSeenAt": 1719792000000,
548
+ "publisherPlatforms": ["GOOGLE_ADS"],
549
+ "regionCodes": ["US", "GB"],
550
+ "variations": [
551
+ {
552
+ "headline": "Summer Sale — 50% Off",
553
+ "description": "Shop our biggest sale of the year.",
554
+ "destinationUrl": "https://example.com/summer-sale",
555
+ "imageUrl": "https://...",
556
+ "visibleUrl": "example.com"
557
+ }
558
+ ],
559
+ "regions": [
560
+ { "code": "US", "name": "United States" }
561
+ ],
562
+ "analysisStatus": "completed",
563
+ "aiAnalysis": {
564
+ "aiSummary": "Promotional display ad for a seasonal sale with urgency-driven CTA",
565
+ "hookAngle": "Discount/Price",
566
+ "offerType": "Percentage Discount",
567
+ "ctaStrategy": "Shop Now",
568
+ "funnelStage": "Bottom",
569
+ "targetAudience": "Price-sensitive shoppers",
570
+ "adFormat": "responsive_display",
571
+ "tags": ["sale", "discount", "ecommerce"],
572
+ "trustSignals": ["Free shipping"],
573
+ "keyMessages": ["50% off", "Free shipping"],
574
+ "competitiveAngle": "Price leadership",
575
+ "dominantColors": ["#FF5733", "#FFFFFF"],
576
+ "analyzedAt": 1719792000000
577
+ }
578
+ }
579
+ ],
580
+ "continueCursor": "eyJwYWdl...",
581
+ "isDone": false
582
+ }
583
+ }
584
+ ```
585
+
586
+ **Key response fields:**
587
+
588
+ | Field | Description |
589
+ |-------|-------------|
590
+ | `headline`, `description` | Top-level ad copy (first variation) |
591
+ | `variations[]` | All ad variations with copy, images, videos, and URLs |
592
+ | `regions[]` | Geographic targeting regions |
593
+ | `impressionsMin/Max` | Estimated impression range (Google Ads Transparency data) |
594
+ | `publisherPlatforms` | Where the ad ran (GOOGLE_ADS, YOUTUBE, etc.) |
595
+ | `analysisStatus` | AI analysis state: `pending`, `processing`, `completed`, `failed` |
596
+ | `aiAnalysis` | AI-generated creative analysis (only present when `analysisStatus` is `completed`) |
597
+ | `aiAnalysis.aiSummary` | One-line AI summary of the ad |
598
+ | `aiAnalysis.hookAngle` | Creative hook (Discount, Fear, Social Proof, etc.) |
599
+ | `aiAnalysis.funnelStage` | Funnel position: Top, Middle, Bottom |
600
+ | `aiAnalysis.tags` | AI-generated tags for filtering |
601
+
602
+ **Flags:**
603
+
604
+ | Flag | Description |
605
+ |---------------|------------------------------------------------|
606
+ | `--search` | Search term for ad text |
607
+ | `--isActive` | Filter by active ads only |
608
+ | `--mediaType` | Filter by media type: `image`, `video`, `text` |
609
+ | `--sort` | Sort: `newest` or `oldest` |
610
+ | `--limit` | Max results per page (default 20, max 100) |
611
+ | `--cursor` | Pagination cursor from previous response |
612
+ | `--output` | Format: `json` \| `csv` \| `md` |
613
+
614
+ ---
615
+
616
+ ### `baker ads google library sync <accountId>`
617
+
618
+ Trigger an immediate re-sync for a tracked account. Polls every 5 seconds until complete (10-minute timeout). Progress is written to stderr.
619
+
620
+ ```bash
621
+ baker ads google library sync acc_def456
622
+ ```
623
+
624
+ **Response:**
625
+
626
+ ```json
627
+ {
628
+ "ok": true,
629
+ "data": {
630
+ "totalAdCount": 350,
631
+ "activeAdCount": 92
632
+ }
633
+ }
634
+ ```
635
+
636
+ ---
637
+
638
+ ### `baker ads google library search-competitors "keyword"`
639
+
640
+ Search for competitors running Google ads for a keyword. Uses DataForSEO (same data as `baker research advertisers`).
641
+
642
+ ```bash
643
+ baker ads google library search-competitors "running shoes"
644
+ baker ads google library search-competitors "crm software" --location uk
645
+ ```
646
+
647
+ **Flags:**
648
+
649
+ | Flag | Description |
650
+ |--------------|----------------------------|
651
+ | `--location` | Location name or code |
652
+ | `--json` | Output in JSON format |
653
+
654
+ ---
655
+
402
656
  ### Staged writes (`baker ads google budgets|campaigns|...`)
403
657
 
404
658
  Write commands **never touch the Google Ads API at stage time**. Each command stages a create/update/pause/resume/remove op against the current chat's draft (`BAKER_CHAT_ID`); the dashboard shows it as a pending "Google Ads" change, and the whole draft applies as one atomic `GoogleAdsService.Mutate` when the chat is published. Feature-flagged per company (`companies.googleAdsWriteEnabled`) — off by default = a fully simulated publish with zero real API calls.
@@ -1690,14 +1944,14 @@ baker images generate "flat geometric mascot, brand palette" \
1690
1944
  --model recraft/recraft-v4.1-pro-vector --rgb-colors "[[10,10,10],[255,80,0]]" --bg-rgb "[255,255,255]"
1691
1945
  ```
1692
1946
 
1693
- **Models** (`--model`, default `google/gemini-3.1-flash-image-preview`):
1947
+ **Models** (`--model`, default `openai/gpt-5.4-image-2`):
1694
1948
 
1695
1949
  | Model | Best for | Aspect ratios | Sizes |
1696
1950
  |---|---|---|---|
1697
- | `google/gemini-3.1-flash-image-preview` **(default)** | Fast iteration, reference editing, extreme aspect ratios (Nano Banana flash) | standard **+** `1:4` `4:1` `1:8` `8:1` | `0.5K`–`4K` |
1951
+ | `openai/gpt-5.4-image-2` **(default)** | Photoreal + cleanest in-image text ad/landing reproduction | standard set | `1K` `2K` `4K` |
1952
+ | `google/gemini-3-pro-image-preview` | Highest fidelity (Nano Banana Pro) | standard set | `1K` `2K` `4K` |
1698
1953
  | `google/gemini-3.5-flash` | Fast; extreme aspect ratios | standard **+** `1:4` `4:1` `1:8` `8:1` | `0.5K`–`4K` |
1699
- | `google/gemini-3-pro-image-preview` | Highest fidelity (Nano Banana Pro) — strong prompt adherence and reference grounding | standard set | `1K` `2K` `4K` |
1700
- | `openai/gpt-5.4-image-2` | Photoreal + cleanest in-image text — ad/landing reproduction | standard set | `1K` `2K` `4K` |
1954
+ | `google/gemini-3.1-flash-image-preview` | Same as 3.5 flash (preview) | extreme set | `0.5K`–`4K` |
1701
1955
  | `recraft/recraft-v4.1-pro-vector` | Vector/flat/SVG-style with palette control | standard set | `1K` `2K` `4K` |
1702
1956
 
1703
1957
  Standard aspect ratios: `1:1` `2:3` `3:2` `3:4` `4:3` `4:5` `5:4` `9:16` `16:9` `21:9`.
@@ -1706,7 +1960,7 @@ Standard aspect ratios: `1:1` `2:3` `3:2` `3:4` `4:3` `4:5` `5:4` `9:16` `16:9`
1706
1960
 
1707
1961
  | Flag | Description |
1708
1962
  |---|---|
1709
- | `--model` | Model id (default `google/gemini-3.1-flash-image-preview`) |
1963
+ | `--model` | Model id (default `openai/gpt-5.4-image-2`) |
1710
1964
  | `--aspect-ratio` | Output aspect ratio (default `1:1`) |
1711
1965
  | `--image-size` | Resolution: `1K` (default) `2K` `4K` (Gemini flash also `0.5K`) |
1712
1966
  | `--reference` | Comma-separated visual references, each either a **public image URL** (Pinterest / stock / library `imageUrl`) **or a local file path** (a sandbox image — brand logo, product shot, cropped photo, screenshot). Local files are downscaled (≤1536px) and inlined automatically — no manual upload. Applied in order; the biggest quality lever for photographed, on-brand output. Split is on `,`, so a URL containing a literal comma in its query string would be torn in two (rare for image CDNs — pass it alone if it occurs); a single `data:` URL is taken whole. |
@@ -2165,17 +2419,13 @@ baker testimonials tags
2165
2419
 
2166
2420
  ### Winning Ads (`baker winning-ads`)
2167
2421
 
2168
- Search the **ad-dna** corpus of scored "winning" competitor ads for reference creatives to reproduce (e.g. with `baker canvas`), and manage the brands your library tracks (`follow` / `following` / `unfollow`). Each result carries a presigned media URL (~1h TTL), the ad's DNA summary, and scores. The CLI authenticates with the normal `BAKER_API_KEY`; the Baker backend proxies the request to the ad-dna service with a server-held token — no extra credential in the sandbox.
2169
-
2170
- > The corpus has **Meta + LinkedIn** connectors, so `--platform` inputs are limited to `meta,linkedin`. (Older result rows may still carry a legacy platform string.)
2422
+ Search the **ad-dna** corpus of scored "winning" competitor ads for reference creatives to reproduce (e.g. with `baker canvas`). Each result carries a presigned media URL (~1h TTL), the ad's DNA summary, and scores. The CLI authenticates with the normal `BAKER_API_KEY`; the Baker backend proxies the request to the ad-dna service with a server-held token — no extra credential in the sandbox.
2171
2423
 
2172
2424
  > Backend env: the Convex deployment must have `AD_DNA_API_TOKEN` set (`npx convex env set AD_DNA_API_TOKEN …`). `AD_DNA_API_URL` is optional and defaults to `https://ads.withbaker.com`.
2173
2425
 
2174
- > Replaces the old `baker ads google library` tree, which has been removed. Competitor-by-keyword discovery still lives at `baker research advertisers`.
2175
-
2176
2426
  ### `baker winning-ads search <query>`
2177
2427
 
2178
- Semantic search (dense recall + BM25 + rerank) → `POST /api/ad-library/winners/search`. The CLI projects each result to a **lean, decision-focused** shape so the agent's context stays small — default fields: `advertiser`, `advertiser_id`, `platform`, `format`, `relevance`, `winner_score`, `summary` (what the ad is about), `media_url`; plus top-level `pool_size`, `match_confidence` (`high|medium|low`), and `below_floor_count` (matches dropped under the relevance floor). `--full` adds DNA detail (`angle`, `target_persona`, `hook_archetype`, `awareness_stage`, `industry`) + longevity (`days_active`, `reach`, `active`, `winner_category`, `media_kind`). `--output json` (default) returns the lean objects; `--output md` prints a table.
2428
+ Semantic search (dense recall + BM25 + rerank). The CLI projects each result to a **lean, decision-focused** shape so the agent's context stays small — default fields: `advertiser`, `advertiser_id`, `platform`, `format`, `relevance`, `winner_score`, `summary` (what the ad is about), `media_url`; plus top-level `pool_size` and `match_confidence`. `--full` adds DNA detail (`angle`, `target_persona`, `hook_archetype`, `awareness_stage`, `industry`) + longevity (`days_active`, `reach`, `active`, `winner_category`, `media_kind`). `--output json` (default) returns the lean objects; `--output md` prints a table.
2179
2429
 
2180
2430
  > `media_url` is the creative itself: for `static` it's the image, for `video` it's the video file. ad-dna stores **no separate poster** for videos, so a video result has only the video URL.
2181
2431
 
@@ -2197,7 +2447,7 @@ baker winning-ads search --ref-ad-id a_12345 --first-seen-after 2026-01-01T00:00
2197
2447
  | `--limit <n>` | Max results 1–100 (**default 10** — shortlist size) |
2198
2448
  | `--max-per-advertiser <n>` | Cap results per advertiser 1–50 (default 3) |
2199
2449
  | `--min-relevance <0-1>` | Relevance floor; trims weak matches |
2200
- | `--platform <list>` | `meta,linkedin` — pass a single value to search **only** that platform |
2450
+ | `--platform <list>` | One or many of `meta,tiktok,linkedin,google_search,google_display,youtube,reddit,x,pinterest,snapchat` — pass a single value to search **only** that platform |
2201
2451
  | `--format <list>` | `video,static,carousel` |
2202
2452
  | `--winner-category <list>` | `winner,scaled_winner,evergreen,rising,untested,dud,…` (default: all) |
2203
2453
  | `--awareness <list>` | `unaware,problem_aware,solution_aware,product_aware,most_aware` |
@@ -2211,21 +2461,20 @@ baker winning-ads search --ref-ad-id a_12345 --first-seen-after 2026-01-01T00:00
2211
2461
 
2212
2462
  Reading the scores: **`relevance`** (0–1) = match of the creative to your query; **`winner_score`** = how proven the ad is in-market. Pick references that are both relevant *and* proven.
2213
2463
 
2214
- ### `baker winning-ads hooks|mechanisms|formats`
2464
+ ### `baker winning-ads hooks|mechanisms|patterns`
2215
2465
 
2216
- Read the **winner-weighted rollup** of the ad-dna corpus `GET /api/ad-library/seed-catalog` the hook /
2217
- mechanism / static-format patterns that actually win, ranked by `winner_score`, keyed on the closed seeds/enums
2218
- the extractor emits (no clustering). Ground a creative in a **proven** pattern for the exact segment instead of
2219
- guessing. (Distinct from `winning-ads patterns`, which contrasts two ad cohorts.)
2466
+ Read the **winner-weighted rollup** of the ad-dna corpus the hook / mechanism / static-format patterns that
2467
+ actually win, ranked by `winner_score`, keyed on the closed seeds/enums the extractor emits (no clustering).
2468
+ Ground a creative in a **proven** pattern for the exact segment instead of guessing.
2220
2469
 
2221
2470
  ```bash
2222
2471
  # Top winning hook seeds for problem-aware SaaS on Meta:
2223
2472
  baker winning-ads hooks --platform meta --awareness problem_aware --industry saas --output md
2224
2473
  # Then narrow a reference search to that proven hook:
2225
2474
  baker winning-ads search "onboarding demo" --hook-archetype callout --output md
2226
- # Also: mechanisms (persuasion), formats (static ad layouts):
2475
+ # Also: mechanisms (persuasion), patterns (static ad layouts):
2227
2476
  baker winning-ads mechanisms --platform linkedin --output md
2228
- baker winning-ads formats --awareness solution_aware --output md
2477
+ baker winning-ads patterns --awareness solution_aware --output md
2229
2478
  ```
2230
2479
 
2231
2480
  | Flag | Purpose |
@@ -2241,66 +2490,13 @@ proven grand-slam pattern floats to the top and a measured dud is floored.
2241
2490
 
2242
2491
  ### `baker winning-ads advertisers <brand>`
2243
2492
 
2244
- List corpus brands by name or domain → `GET /api/ad-library/advertisers`. Use it to find **your own** advertiser (to `--exclude-advertiser`) or a **competitor** (to `--advertiser-id` / `winners`). Lean default fields: `advertiser_id`, `label`, `platform_count`, `family_count`, `active_ad_count`, `total_ad_count`; `--full` adds `scraped_name`, `image_url`, `platforms`, `total_reach`, `last_synced_at`. Supports `--platform meta|linkedin`, `--limit`, `--offset`.
2493
+ Resolve a brand name → `advertiser_id`(s) in the corpus. Use it to find **your own** advertiser (to `--exclude-advertiser`) or a **competitor** (to `--advertiser-id`). Returns `advertiser_id`, `label`, `active_ads`, `total_ads`.
2245
2494
 
2246
2495
  ```bash
2247
2496
  baker winning-ads advertisers "Acme" --output md # find our own advertiser id
2248
2497
  baker winning-ads advertisers "Deel" --platform meta --output md
2249
2498
  ```
2250
2499
 
2251
- ### `baker winning-ads follow "<domain | profile URL | brand>" --platform meta|linkedin`
2252
-
2253
- Add **all** of a brand's ads to your library — every platform (Meta + LinkedIn) and every country → `POST /api/ad-library/follow`. `--platform` is **required**, but it only tells us how to read your `input` (Facebook vs LinkedIn URL); it does **not** limit what we track. A bare domain is best: we resolve both the Meta page and the LinkedIn company from it and track both. Discovery is never region-scoped. The result `status` is one of:
2254
-
2255
- - `following` — the brand is already in the corpus; you're now subscribed (no wait).
2256
- - `added` — a new brand was queued for ingestion; its ads appear as discovery completes (a `hints[]` note flags this).
2257
- - `ambiguous` — the input mapped to multiple brands; pick one from `candidates` and re-run with a more specific domain/URL.
2258
-
2259
- ```bash
2260
- baker winning-ads follow "deel.com" --platform meta
2261
- baker winning-ads follow "https://www.linkedin.com/company/acme" --platform linkedin --label "Acme (competitor)"
2262
- ```
2263
-
2264
- ### `baker winning-ads following`
2265
-
2266
- List the brands you follow → `GET /api/ad-library/following`. Each row shows `status` (`ready` vs `adding…`) plus cached counts (`active_ad_count`, `total_ad_count`, `family_count`) and discovery progress (`adding_discovered`, `adding_enqueued`). `--full` adds `image_url` + `platforms`.
2267
-
2268
- ```bash
2269
- baker winning-ads following --output md
2270
- ```
2271
-
2272
- ### `baker winning-ads winners <advertiser>`
2273
-
2274
- Top winning ads for one advertiser id → `GET /api/ad-library/advertiser-winners`. Same lean winner cards as `search` (add `--full` for DNA + longevity). Supports `--top N` and `--platform meta|linkedin`.
2275
-
2276
- ```bash
2277
- baker winning-ads winners adv_123 --top 15 --output md
2278
- ```
2279
-
2280
- ### `baker winning-ads unfollow <advertiser>`
2281
-
2282
- Stop following a brand by advertiser id → `POST /api/ad-library/unfollow`. Returns `{ removed }`.
2283
-
2284
- ```bash
2285
- baker winning-ads unfollow adv_123
2286
- ```
2287
-
2288
- ### `baker winning-ads brief`
2289
-
2290
- Generate a creative brief grounded in strategically-similar winners → `POST /api/ad-library/brief`. Optionally describe the target creative with `--dna` (a JSON object), steer with `--notes`, and cap references with `--k`. Returns `brief_markdown` + `reference_ad_ids`.
2291
-
2292
- ```bash
2293
- baker winning-ads brief --dna '{"angle":"cost savings","awareness_stage":"solution_aware"}' --notes "B2B, LinkedIn video" --k 8
2294
- ```
2295
-
2296
- ### `baker winning-ads patterns --winners <adIds> --duds <adIds>`
2297
-
2298
- Mine what separates two cohorts of ads → `POST /api/ad-library/patterns`. Pass a comma-list of winning ad ids (`--winners`, cohort A) and weaker/dud ad ids (`--duds`, cohort B), plus optional `--top-n`. Returns each discriminating DNA field with the cohort it `favors` (`winners`/`duds`), a `score`, and the top values on each side.
2299
-
2300
- ```bash
2301
- baker winning-ads patterns --winners a_1,a_2,a_3 --duds a_9,a_8 --top-n 10 --output md
2302
- ```
2303
-
2304
2500
  ---
2305
2501
 
2306
2502
  ### Scheduled Actions (`baker scheduled-actions`)
@@ -3,9 +3,9 @@ import {
3
3
  __toESM
4
4
  } from "./chunk-5WRI5ZAA.js";
5
5
 
6
- // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
6
+ // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js
7
7
  var require_safe_stable_stringify = __commonJS({
8
- "../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
8
+ "../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/index.js"(exports, module) {
9
9
  "use strict";
10
10
  var { hasOwnProperty } = Object.prototype;
11
11
  var stringify = configure2();
@@ -979,7 +979,7 @@ function describeCause(c) {
979
979
  }
980
980
  }
981
981
 
982
- // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
982
+ // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/810146e81bae4e3a061fe487864f2fde80c4b03b886877dc0f1fffbc6480b67e/node_modules/safe-stable-stringify/esm/wrapper.js
983
983
  var import__ = __toESM(require_safe_stable_stringify(), 1);
984
984
  var configure = import__.default.configure;
985
985
  var wrapper_default = import__.default;
@@ -7696,4 +7696,4 @@ export {
7696
7696
  defaultRegistry,
7697
7697
  createEngineFromEnv
7698
7698
  };
7699
- //# sourceMappingURL=chunk-AEBAUSIN.js.map
7699
+ //# sourceMappingURL=chunk-5LCTMZJ5.js.map