@koda-sl/baker-cli 0.355.0-dev.c2de9a6fe → 0.356.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 CHANGED
@@ -98,7 +98,12 @@ All commands return a JSON envelope:
98
98
  ### Unknown options are refused
99
99
 
100
100
  An option a command does not declare stops the run with `UNKNOWN_ARGUMENT`, naming the
101
- closest real one. Previously such an option was accepted and ignored, so a call that
101
+ real one it was most likely reaching for, with the first sentence of that option's own
102
+ description. A word the command spells differently is matched by meaning (`--from` and
103
+ `--since` → `--start-date`, `--to` and `--until` → `--end-date`, `--path` and `--url` →
104
+ `--landing`, each only where the command has it); otherwise only a near spelling is
105
+ offered, so a short option is never pointed at an unrelated one (`--from` at `--full`).
106
+ Previously such an option was accepted and ignored, so a call that
102
107
  looked like it had filtered or narrowed a result was in fact answering the unfiltered
103
108
  question — and nothing in the output said so. Both spellings of an option work
104
109
  (`--run-id` and `--runId`), as they always did. The error's `fix` names the exact call
@@ -1333,7 +1338,7 @@ Shared flags: `--days <n>` (default 30) or `--start-date` / `--end-date` (`YYYY-
1333
1338
 
1334
1339
  `--measure` decides whose activity is measured and defaults to `campaigns` (only visitors a Baker landing brought). `--measure all` measures the client's entire website and is a decision somebody has to ask for. `host` is the client's own landing domain when one shares a domain with the site being measured, so the script and its events stay first-party; `firstParty` in the response says which, and removing that domain from Baker means re-running this command.
1335
1340
 
1336
- **Paging the list reports.** `people`, `submissions` and `delivery` are lists of individual things rather than breakdowns — `delivery` and `submissions` are the ones the CLI exposes, `people` backs the People section of the dashboard's landing Analytics screen over the same wire — and only they take `--page <n>` (1-based) and `--page-size <n>` (up to 200, default 50). The response carries `pageInfo` with `hasMore` — when it is true there **are** more rows, so a total must never be reported from one page. Pass neither flag and a list comes back at the size it always did.
1341
+ **Paging the list reports.** `people`, `submissions` and `delivery` are lists of individual things rather than breakdowns — `delivery` and `submissions` are the ones the CLI exposes, `people` backs the People section of the dashboard's landing Analytics screen over the same wire — and only they take `--page <n>` (1-based) and `--page-size <n>` (up to 200, default 50). The response carries `pageInfo` with `hasMore` — when it is true there **are** more rows, so a total must never be reported from one page. Pass neither flag and a list comes back at the size it always did. A value that is not a whole positive number (`--page /pricing`) is refused before any request, naming `--landing` as the flag that narrows a report to one page of the site.
1337
1342
 
1338
1343
  **A conversion is a company-level named event, not a property of a Form.** `baker analytics conversions` is the only place "what counts" is decided, and an empty `definitions` list means every conversion number in every other report is zero — not because nobody converted, but because nothing is named as an outcome and Baker never guesses which event is the point of a page. `--candidates` lists every event these pages actually produced — each Form step and trigger, every `data-baker-*` event, every outbound destination — with volume and whether it is already counted; that list is where an event key comes from, so never invent one. `--event <key> --name "Booked a call"` starts counting it **immediately and retroactively**: the whole stored history is rescored, so naming the right event today also fixes last month. Nothing here is staged and publishing is not involved. Two events given the same `--name` become one row and one number, which is how a call booked on three different Forms reads as one outcome. `--count-mode every_time` is for the outcomes people genuinely repeat (a guide downloaded twice is two downloads); the default counts once per visit.
1339
1344
 
@@ -5350,6 +5355,11 @@ and the canvas file is saved, before anything else reads it. `normalized_paths`
5350
5355
  wrote it, so validate, run, and the preview all pass, and only the publish build — a different checkout
5351
5356
  root, a different session — ever sees the break.
5352
5357
 
5358
+ **A URL in an ingest's `path` is healed the same way.** A `source: "path"` ingest whose `path` is an
5359
+ http(s) URL already runs as `source: "url"`; `validate` and `run` rewrite the file to say so
5360
+ (`normalized_paths` lists it as `{ param: "source", from: "path", to: "url" }`), so the commit gate,
5361
+ which reads the file, agrees with what rendered.
5362
+
5353
5363
  Two roots count as "this workspace": the current one, and `/home/user/repo` (`REPO_PATH`), the fixed path
5354
5364
  every Session's workspace is checked out at. A path under either names the same file in any checkout, so
5355
5365
  remapping it is a proof rather than a guess — which is what lets an already-committed canvas heal in the
@@ -5412,7 +5422,7 @@ Before the deconstruct it runs a **local shot-cut pass** on the source file with
5412
5422
 
5413
5423
  A shot longer than the video model's per-clip ceiling (Seedance's 15s, passed as `video_deconstruct`'s `max_clip_s`) is split into equal **continuation sub-scenes** that share their splice boundary exactly — so a long shot is reproduced in **full** (no truncation) and joins seamlessly. Each sub-scene carries `continues_previous`.
5414
5424
 
5415
- It then scaffolds the full pipeline like an **editing timeline**: each clip gets a **static-ad-grade start AND end keyframe** (`image_generate`, each with its **own `params.prompt`** regenerated from that scene's `scenes/sNN.json` — edit the scene file to change that frame, never the node prompt by hand; the slim `prompt.style.json` wired as the **shared `target_blueprint`** style reference, plus a per-element reference legend). Each keyframe is **fully recast** to the dropped `el_*` reference images. The original extracted frame is kept LAST as a **pure composition anchor** (framing / camera angle / shot size / pose) whenever identity is safely locked — i.e. a frame with no person/animal, OR every cast member present is **sheet-backed** (a multi-view turnaround owns identity, so the anchor can reproduce the source's framing without dictating the face). Since every base element is now sheet-backed by default, cast frames keep their framing anchor too — this is what reproduces the source's composition (a side-profile stays a side-profile, the camera angle holds scene to scene) instead of drifting to a fresh guess. The anchor's legend forbids taking identity/text/palette from it. It is dropped only when a cast member rests on a weak lone-snapshot reference (e.g. a `same_as` second-look slot), where the original frame could re-leak the source actor. Both keyframes feed `video_generate` (`first_frame`+`last_frame`, so Seedance interpolates real in-shot motion; ultra-detailed motion brief; duration snapped to the nearest allowed clip length). Every keyframe grounds **only on its own extracted frame + `el_*` slots** — no reference to any other generated frame — so all images render **in parallel** (no cascade). Source-frame URLs are **deduped** (each ingested once). `--frames reuse` wires the real source frame straight in — only on a video with nobody in it: when the deconstruct found a cast or a recurring person, reuse is refused (`frames_reuse_refused`) and every frame is generated, so the source's actors never reach the ad.
5425
+ It then scaffolds the full pipeline like an **editing timeline**: each clip gets a **static-ad-grade start AND end keyframe** (`image_generate`, each with its **own `params.prompt`** regenerated from that scene's `scenes/sNN.json` — edit the scene file to change that frame, never the node prompt by hand; the slim `prompt.style.json` wired as the **shared `target_blueprint`** style reference, plus a per-element reference legend). Each keyframe is **fully recast** to the dropped `el_*` reference images. The original extracted frame is kept LAST as a **pure composition anchor** (framing / camera angle / shot size / pose) whenever identity is safely locked — i.e. a frame with no person/animal, OR every cast member present is **sheet-backed** (a multi-view turnaround owns identity, so the anchor can reproduce the source's framing without dictating the face). Since every base element is now sheet-backed by default, cast frames keep their framing anchor too — this is what reproduces the source's composition (a side-profile stays a side-profile, the camera angle holds scene to scene) instead of drifting to a fresh guess. The anchor's legend forbids taking identity/text/palette from it. It is dropped only when a cast member rests on a weak lone-snapshot reference (e.g. a `same_as` second-look slot), where the original frame could re-leak the source actor. Both keyframes feed `video_generate` (`first_frame`+`last_frame`, so Seedance interpolates real in-shot motion; ultra-detailed motion brief; duration snapped to the nearest allowed clip length). Every keyframe grounds **only on its own extracted frame + `el_*` slots** — no reference to any other generated frame — so all images render **in parallel** (no cascade). Source-frame URLs are **deduped** (each ingested once). `--frames reuse` wires the real source frame straight in.
5416
5426
 
5417
5427
  **Composited scenes (split-screen / picture-in-picture / keyed presenter).** Real ads aren't always one full-frame shot — a frame can be **persistently divided** (b-roll on top, a presenter talking on the bottom) or **layer a presenter** over background footage (boxed in a corner, or green-screen keyed). The deconstruct now reports this per scene as `scene.composition` (`layout: split_screen | pip | keyed_overlay`, with one `region` per stream — each its own clean-plate frame + motion brief, the talking-head region flagged `is_presenter`). The scaffold reproduces a composited scene by building **one clip per region** (`s<i>_r0_*`, `s<i>_r1_*`, …) and compositing them with ffmpeg: a split-screen `vstack`/`hstack` (stack direction read from the region **panels**, so a top/bottom split always stacks vertically), or a picture-in-picture `overlay` of the presenter inset at its corner. A **keyed** presenter is first cut to transparency by `video_background_remove` (`s<i>_key`), then overlaid. The presenter region carries the native lip-synced voice; b-roll/render panels stay silent. To change a layout, edit `composition` in that scene's `scenes/sNN.json` and re-scaffold, or hand-edit the `s<i>_composite` ffmpeg args. Plain full-frame scenes (the default) are unaffected.
5418
5428
 
@@ -5466,7 +5476,7 @@ baker canvas run ./reference-ad.video.canvas.json
5466
5476
  |---|---|---|
5467
5477
  | `--out <path>` | `<video-dir>/<name>.video.canvas.json` | Where to write the canvas (composition is copied alongside). |
5468
5478
  | `--slug <slug>` | — | Creative slug (lowercase kebab): writes the canvas to `src/creatives/<slug>/<slug>.canvas.json` — the repo convention that attaches every run to the creative's dashboard generation history. `--out` wins over `--slug`. |
5469
- | `--frames <mode>` | `generate` | `generate` emits ONE recast keyframe per scene (the original frame is dropped so the dropped `el_*` assets drive identity); `reuse` wires the real extracted first+last frames straight into the clips (faithful, cheaper, no recast) — only on a video with nobody in it; on one showing people it is refused and every frame is generated. |
5479
+ | `--frames <mode>` | `generate` | `generate` emits ONE recast keyframe per scene (the original frame is dropped so the dropped `el_*` assets drive identity); `reuse` wires the real extracted first+last frames straight into the clips (faithful, cheaper, no recast). |
5470
5480
  | `--ambient` | off | Give silent **b-roll** scenes native diegetic ambient (Seedance `generate_audio`), mixed deep under the music bed. Talking scenes already carry voice; check levels don't muddy the mix before keeping it. |
5471
5481
  | `--seam-dedup <mode>` | `head` | How to dedup the boundary frame two clips SHARE when a long shot is split for length (the second clip's first frame IS the first clip's last frame, so a plain concat freezes on it for a frame). `head` drops the second clip's first frame, `tail` drops the first clip's last frame, `off` keeps both. Only touches shared-frame continuation joins — a hard cut between two shots shares no frame. |
5472
5482
  | `--max-scenes <n>` | all source scenes | **Cost lever that reduces fidelity** — caps the deconstruct, MERGING away every scene beyond the cap (fewer cuts, lost beats). Prints a warning when set; omit it to reproduce every scene. |
@@ -20,9 +20,9 @@ import {
20
20
  shouldEscalate
21
21
  } from "./chunk-2OKSJNLA.js";
22
22
 
23
- // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/index.js
23
+ // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
24
24
  var require_safe_stable_stringify = __commonJS({
25
- "../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/index.js"(exports, module) {
25
+ "../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
26
26
  "use strict";
27
27
  var { hasOwnProperty } = Object.prototype;
28
28
  var stringify = configure2();
@@ -1114,7 +1114,7 @@ function resolveAdaptFormats(params) {
1114
1114
  return params.formats ?? [];
1115
1115
  }
1116
1116
 
1117
- // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/esm/wrapper.js
1117
+ // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
1118
1118
  var import__ = __toESM(require_safe_stable_stringify(), 1);
1119
1119
  var configure = import__.default.configure;
1120
1120
  var wrapper_default = import__.default;
@@ -9866,6 +9866,7 @@ export {
9866
9866
  isAudioOnly,
9867
9867
  durationSeconds,
9868
9868
  canonicalUrl,
9869
+ coercePathUrlToUrl,
9869
9870
  toModelSafeImage,
9870
9871
  catalogView,
9871
9872
  BackendClient2,
@@ -9878,4 +9879,4 @@ export {
9878
9879
  defaultRegistry,
9879
9880
  createEngineFromEnv
9880
9881
  };
9881
- //# sourceMappingURL=chunk-B7MLH3K6.js.map
9882
+ //# sourceMappingURL=chunk-H3SAAHZA.js.map