@letterstory/cli 0.58.0 → 0.60.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
@@ -360,8 +360,9 @@ letterstory admin tuning comparison <id> # per-measure verdicts (b
360
360
  letterstory admin tuning picks <id> # the blind queue; then: admin tuning pick <id> --cell <key> --pick left|right|tie
361
361
  letterstory admin tuning reading-list <id> --n 10 # your next blind pairs as links (Text A / Text B), to read off the screen; pick in the console
362
362
  letterstory admin tuning pair <id> --cell <key> # one pair named: live and candidate, both texts, the measures per arm (a key reads every pair)
363
+ letterstory admin tuning side-by-side <id>,<id>,<id> [--cell <key>] # several writers as one board: each one's measures against live; with --cell, every writer's text on that input
363
364
  letterstory admin tuning candidates --kernels all --patch '{"writer":"echo/echo"}' --note "Echo" # the same change as a candidate of each kernel
364
- letterstory admin tuning session-new --title "Echo round 1" --kernel Hazel --input-file brief.md --kind outline [--version 22]
365
+ letterstory admin tuning session-new --title "Echo round 1" --kernel Hazel --input-file brief.md --kind outline [--version 22] [--versions 23,29] # --versions: saved candidates, a trial each
365
366
  letterstory admin tuning propose <session> --text "Echo with rarity on; live with the shred after" --create # trials from words, over the dials
366
367
  letterstory admin tuning trial-run <trial> --repeats 2 # runs advance on the server; poll `admin tuning session <id> --texts`
367
368
  letterstory admin tuning trial-save <trial> --note "…" # a trial as a candidate version (never live); then `admin tuning compare`
package/lib/cli.mjs CHANGED
@@ -55,7 +55,7 @@ import {
55
55
  } from "./commands.mjs";
56
56
 
57
57
  // Keep in sync with cli/package.json.
58
- export const VERSION = "0.58.0";
58
+ export const VERSION = "0.60.0";
59
59
 
60
60
  // Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
61
61
  // can't accidentally swallow the id as --json's value.
@@ -430,6 +430,7 @@ async function cmdAdminTuningContext(ctx) {
430
430
  * admin tuning pick <comparison-id> --cell <key> --pick left|right|tie record a blind pick
431
431
  * admin tuning reading-list <comparison-id> [--n 10] your next blind pairs as links, to read off the screen
432
432
  * admin tuning pair <comparison-id> --cell <key> one pair named: live and candidate, both texts, the measures per arm
433
+ * admin tuning side-by-side <id>,<id>[,…] [--cell <key>] several comparisons as one board: each writer's measures against live, and one input's texts
433
434
  * admin tuning candidates --kernels Hazel,Aspen|all --patch '{…}' [--base N] [--note "…"] the same changes as a candidate of each kernel
434
435
  * admin tuning promote <experiment-id> --versions <service-kernel-id>:<version>,… promote from a "ship" decision
435
436
  *
@@ -640,6 +641,34 @@ async function cmdAdminTuning(ctx) {
640
641
  await staffRequest(ctx, "GET", `${T}/comparisons/${id}/pair?${new URLSearchParams({ cell })}`)
641
642
  );
642
643
  }
644
+ case "side-by-side": {
645
+ const ids = (id ?? "")
646
+ .split(",")
647
+ .map((x) => x.trim())
648
+ .filter(Boolean);
649
+ if (!ids?.length) throw new CliError("Usage: admin tuning side-by-side <id>,<id>[,…] [--cell <key>]");
650
+ const cell = flagStr(flags.cell);
651
+ const r = await staffRequest(
652
+ ctx,
653
+ "GET",
654
+ `${T}/comparisons/side-by-side?${new URLSearchParams(compact({ ids: ids.join(","), cell }))}`
655
+ );
656
+ if (json) return printResult(io, flags, r);
657
+ for (const w of r.writers) {
658
+ const m = (measure) => w.measures.find((x) => x.measure === measure);
659
+ const q = m("quality");
660
+ io.log(
661
+ `${w.label} (${w.writers.join(", ") || "—"}, ${w.settled_pairs} pairs, ${w.status}): quality ${q?.mean_delta ?? "—"} [${q?.ci95?.join(" … ") ?? "—"}] ${q?.verdict ?? ""} · seconds ${m("latency_s")?.mean_candidate ?? "—"} vs ${m("latency_s")?.mean_control ?? "—"} · picks ${w.picks.candidate}–${w.picks.control}`
662
+ );
663
+ }
664
+ if (r.input) {
665
+ for (const t of [r.input.live, ...r.input.texts].filter(Boolean))
666
+ io.log(
667
+ `\n=== ${t.label} ${t.writer ?? ""}${t.version ? ` v${t.version}` : ""} (${t.access})\n${t.text ?? "(no text)"}`
668
+ );
669
+ } else io.log(`\ninputs: ${r.inputs.map((i) => i.key).join(", ")} (add --cell <key> for the texts)`);
670
+ return;
671
+ }
643
672
  case "candidates": {
644
673
  const patch = jsonFlag(flags.patch, "--patch");
645
674
  const wanted = flagList(flags.kernels);
@@ -730,7 +759,7 @@ async function cmdAdminTuning(ctx) {
730
759
  }
731
760
  if (!title || !kernel || !input)
732
761
  throw new CliError(
733
- 'Usage: admin tuning session-new --title "…" --kernel <id|name> (--input-file f.md | --input "…") [--kind article|outline|brief] [--version N] [--writers a,b] [--trials-from <session-id>]'
762
+ 'Usage: admin tuning session-new --title "…" --kernel <id|name> (--input-file f.md | --input "…") [--kind article|outline|brief] [--version N] [--writers a,b] [--versions 23,29] [--trials-from <session-id>]'
734
763
  );
735
764
  let kernelId = kernel;
736
765
  if (!/^[0-9a-f-]{36}$/i.test(kernel)) {
@@ -752,6 +781,11 @@ async function cmdAdminTuning(ctx) {
752
781
  base_version: flagNum(flags.version),
753
782
  trials_from_session_id: flagStr(flags["trials-from"]),
754
783
  writers: (flagList(flags.writers) ?? []).map((model) => ({ model })),
784
+ // Candidates to compare: other versions of the base kernel, a trial each.
785
+ versions: (flagList(flags.versions) ?? [])
786
+ .flatMap((v) => v.split(","))
787
+ .map((v) => Number(v.trim()))
788
+ .filter((v) => Number.isInteger(v) && v > 0),
755
789
  })
756
790
  );
757
791
  if (json) return printResult(io, flags, { session });
@@ -1141,7 +1175,7 @@ async function cmdAdminTuning(ctx) {
1141
1175
  }
1142
1176
  default:
1143
1177
  throw new CliError(
1144
- "Usage: admin tuning kernels|kernel|candidate|compare|comparisons|comparison|picks|pick|reading-list|pair|candidates|base-kernels|base-versions|sessions|session|session-new|propose|trial-add|trial-run|trial-save|promote|arenas|arena|arena-candidate|research-compare|research-inputs|research-split|research-standing|promote-arena|shred-compare|shred-inputs|shred-split|shred-standing|shredders|shredder|shredder-candidate|promote-shredder|enhance-compare|enhance-inputs|enhance-split|enhance-standing|enhancers|enhancer|enhancer-candidate|promote-enhancer (see --help)"
1178
+ "Usage: admin tuning kernels|kernel|candidate|compare|comparisons|comparison|picks|pick|reading-list|pair|side-by-side|candidates|base-kernels|base-versions|sessions|session|session-new|propose|trial-add|trial-run|trial-save|promote|arenas|arena|arena-candidate|research-compare|research-inputs|research-split|research-standing|promote-arena|shred-compare|shred-inputs|shred-split|shred-standing|shredders|shredder|shredder-candidate|promote-shredder|enhance-compare|enhance-inputs|enhance-split|enhance-standing|enhancers|enhancer|enhancer-candidate|promote-enhancer (see --help)"
1145
1179
  );
1146
1180
  }
1147
1181
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.58.0",
3
+ "version": "0.60.0",
4
4
  "description": "Spin up and manage Letterstory phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",