@letterstory/cli 0.94.0 → 0.96.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
@@ -353,6 +353,7 @@ long-running agent can watch the fleet on a schedule without a browser.
353
353
  # every client against itself on share of voice, mention rate and page access, with what we
354
354
  # did for it. Needs fleet:read; `run` and `ask` spend Fable tokens and need fleet:query.
355
355
  letterstory admin patterns --period 30d
356
+ letterstory admin patterns kernels --by version --outcome impressions14 # what each kernel/version change did
356
357
  letterstory admin patterns reports # Fable's weekly reports and runs, newest first
357
358
  letterstory admin patterns report <id> # one report's markdown
358
359
  letterstory admin patterns run # a report now (takes minutes)
package/lib/cli.mjs CHANGED
@@ -58,7 +58,7 @@ import {
58
58
  } from "./commands.mjs";
59
59
 
60
60
  // Keep in sync with cli/package.json.
61
- export const VERSION = "0.94.0";
61
+ export const VERSION = "0.96.0";
62
62
 
63
63
  // Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
64
64
  // can't accidentally swallow the id as --json's value. Every `type: "bool"` flag (and its
@@ -660,6 +660,10 @@ Admin (STAFF key — --staff-key / LETTERSTORY_STAFF_API_KEY; acts before an org
660
660
  Client patterns: every client's share of voice,
661
661
  mention rate and page access against itself, with
662
662
  what we did for it. Needs fleet:read.
663
+ admin patterns kernels [--by version|family] [--outcome cited14|read14|named|impressions14|clicks14|cited28|impressions28]
664
+ What each kernel and version change did: the client's
665
+ change minus clients that held still, pooled by
666
+ transition. Needs fleet:read.
663
667
  admin patterns reports [--kind reports|weekly|run|ask] | report <id>
664
668
  Fable's weekly reports, runs and Ask Fable answers.
665
669
  admin patterns run | ask "<question>" Run a Fable report now, or ask Fable a question
@@ -4,7 +4,7 @@
4
4
  // routes, because they exist precisely to act BEFORE an org exists.
5
5
  //
6
6
  // admin ask "which kernels are hooked up to the most clients?" [--sql] [--json]
7
- // admin patterns [--period 14d|30d] [--segment "…"] | reports [--kind reports|weekly|run|ask] | report <id> | run | ask "<question>" (fleet:read / fleet:query)
7
+ // admin patterns [--period 14d|30d] [--segment "…"] | kernels [--by version|family] [--outcome cited14] | reports [--kind reports|weekly|run|ask] | report <id> | run | ask "<question>" (fleet:read / fleet:query)
8
8
  // admin experiments list|show|new|update|note|started|spend|conclude|abandon … (tuning:experiment)
9
9
  // admin tuning-context [--q "<question>"] (tuning:experiment)
10
10
  // admin tuning-import <brief-results.json> [--experiment <id>] (tuning:experiment)
@@ -273,6 +273,28 @@ async function cmdAdminPatterns(ctx) {
273
273
  }
274
274
  return;
275
275
  }
276
+ case "kernels": {
277
+ const params = new URLSearchParams();
278
+ if (flagStr(ctx.flags.by)) params.set("by", flagStr(ctx.flags.by));
279
+ if (flagStr(ctx.flags.outcome)) params.set("outcome", flagStr(ctx.flags.outcome));
280
+ const result = await staffRequest(ctx, "GET", `${PATTERNS}/kernels${params.size ? `?${params}` : ""}`);
281
+ if (json) return printResult(ctx.io, ctx.flags, result);
282
+ const fmt = (v) => (v == null ? "—" : `${v >= 0 ? "+" : "−"}${Math.abs(v).toFixed(3)}`);
283
+ ctx.io.log(
284
+ `Kernel changes on ${result.outcome}, by ${result.by} (effect = change minus clients that held still):`
285
+ );
286
+ for (const t of result.transitions)
287
+ ctx.io.log(
288
+ ` ${`${t.from} → ${t.to}`.padEnd(30)} ${fmt(t.effect)} (${fmt(t.lo)} to ${fmt(t.hi)}) ${t.verdict} · ${t.swaps} swaps, ${t.clients} clients`
289
+ );
290
+ if (!result.transitions.length) ctx.io.log(" none yet");
291
+ ctx.io.log(`\n${result.by === "version" ? "Versions" : "Kernels"} (descriptive):`);
292
+ for (const k of result.kernels)
293
+ ctx.io.log(
294
+ ` ${k.label.padEnd(16)} ${String(k.posts).padStart(6)} posts ${String(k.clients).padStart(4)} clients ${k.outcome ? k.outcome.mean.toFixed(3) : "—"}`
295
+ );
296
+ return;
297
+ }
276
298
  case "reports": {
277
299
  const kind = flagStr(ctx.flags.kind) ?? "reports";
278
300
  const limit = flagStr(ctx.flags.limit) ?? "12";
@@ -312,7 +334,9 @@ async function cmdAdminPatterns(ctx) {
312
334
  return;
313
335
  }
314
336
  default:
315
- throw new CliError('Usage: admin patterns [show] | reports | report <id> | run | ask "<question>"');
337
+ throw new CliError(
338
+ 'Usage: admin patterns [show] | kernels | reports | report <id> | run | ask "<question>"'
339
+ );
316
340
  }
317
341
  }
318
342
 
@@ -615,6 +639,8 @@ async function cmdAdminTuningContext(ctx) {
615
639
  * admin tuning arenas | arena <version-id> our arena's versions / one version's file and diff
616
640
  * admin tuning arena-candidate --patch '{…}' | --file f.json [--of <version-id>] [--note "…"] save a candidate
617
641
  * admin tuning research-compare --title "…" (--candidate <version-id> | --patch '{…}' | --null-check) [--keys …]
642
+ * admin tuning research-compare … --write Hazel write every arm into an article with one kernel
643
+ * (live version, pinned): the arena the only difference, read with Write's measures and blind
618
644
  * admin tuning research-compare --title "…" --candidates <version-id>,… | --patches '[{…},{…}]' several
619
645
  * candidates against ONE control arm (k + 1 runs per input, not 2k)
620
646
  * admin tuning arena-dials every arena setting: help, default, evidence, live's value
@@ -1971,7 +1997,7 @@ async function cmdAdminTuning(ctx) {
1971
1997
  ].filter(Boolean).length;
1972
1998
  if (!title || named !== 1)
1973
1999
  throw new CliError(
1974
- "Usage: admin tuning research-compare --title \"…\" (--candidate <version-id> | --patch '{…}' | --null-check | --candidates <id>,… [--patches '[{…},…]']) [--keys k1,k2] [--concurrency 6] [--experiment <id>]"
2000
+ "Usage: admin tuning research-compare --title \"…\" (--candidate <version-id> | --patch '{…}' | --null-check | --candidates <id>,… [--patches '[{…},…]']) [--write Hazel] [--keys k1,k2] [--concurrency 6] [--experiment <id>]"
1975
2001
  );
1976
2002
  const several =
1977
2003
  versionIds?.length || patches?.length
@@ -1996,6 +2022,8 @@ async function cmdAdminTuning(ctx) {
1996
2022
  title,
1997
2023
  candidate,
1998
2024
  candidates: several,
2025
+ // The kernel that writes every arm into a finished article (the arena the only difference).
2026
+ write: flagStr(flags.write) ? { kernel: flagStr(flags.write) } : undefined,
1999
2027
  keys: flagList(flags.keys),
2000
2028
  concurrency: flagNum(flags.concurrency),
2001
2029
  experiment_id: flagStr(flags.experiment),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.94.0",
3
+ "version": "0.96.0",
4
4
  "description": "Spin up and manage Letterstory phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",