@letterstory/cli 0.176.79 → 0.176.81

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/lib/cli.mjs CHANGED
@@ -85,7 +85,7 @@ import {
85
85
  import { fetchParkedSections, withoutParked } from "./parked.mjs";
86
86
 
87
87
  // Matches cli/package.json; publish-cli.yml rewrites both to the published version.
88
- export const VERSION = "0.176.79";
88
+ export const VERSION = "0.176.81";
89
89
 
90
90
  /** The exit code for a gate refusal (CARD_REQUIRED, PAYMENT_FAILED, OUT_OF_TOKENS): 1 is a plain error. */
91
91
  export const EXIT_PAYMENT_REQUIRED = 3;
@@ -274,9 +274,9 @@ export const BOOLEAN_FLAGS = new Set([
274
274
  "resolve",
275
275
  "reopen",
276
276
  "skip",
277
- // `phantom-onboard domain` / `admin create-org --onboard` switches.
277
+ // `phantom-onboard domain` / `admin create-org --onboard` switches. (`--status` is a switch only on
278
+ // phantom-onboard, SWITCH_FLAGS_BY_COMMAND: everywhere else it takes a value, `--status parked`.)
278
279
  "watch",
279
- "status",
280
280
  "no-phantom",
281
281
  "no-visuals",
282
282
  "no-enhance",
@@ -424,6 +424,13 @@ export const BOOLEAN_FLAGS = new Set([
424
424
  */
425
425
  const VALUE_FLAGS_BY_COMMAND = { automations: new Set(["on"]) };
426
426
 
427
+ /**
428
+ * Flags that are switches on one command and take a value everywhere else. `--status` is "show me the job" on
429
+ * phantom-onboard (onboard.mjs), and a value on every other (`admin recipes save --status parked`, `admin crm
430
+ * prospect-orgs --status ready`): as a global switch, `--status parked` dropped "parked" (2026-11-09).
431
+ */
432
+ export const SWITCH_FLAGS_BY_COMMAND = { "phantom-onboard": new Set(["status"]), onboard: new Set(["status"]) };
433
+
427
434
  /**
428
435
  * @param {string[]} argv
429
436
  * @returns {{ positionals: string[], flags: Record<string, string | boolean | string[]> }}
@@ -432,6 +439,7 @@ export function parseArgs(argv) {
432
439
  const positionals = [];
433
440
  const flags = {};
434
441
  const valueFlags = VALUE_FLAGS_BY_COMMAND[argv[0]] ?? new Set();
442
+ const switchFlags = SWITCH_FLAGS_BY_COMMAND[argv[0]] ?? new Set();
435
443
  const setFlag = (name, value) => {
436
444
  if (Object.prototype.hasOwnProperty.call(flags, name)) {
437
445
  flags[name] = [].concat(flags[name], value);
@@ -452,7 +460,12 @@ export function parseArgs(argv) {
452
460
  }
453
461
  const name = tok.slice(2);
454
462
  const next = argv[i + 1];
455
- if ((BOOLEAN_FLAGS.has(name) && !valueFlags.has(name)) || next === undefined || next.startsWith("--")) {
463
+ if (
464
+ (BOOLEAN_FLAGS.has(name) && !valueFlags.has(name)) ||
465
+ switchFlags.has(name) ||
466
+ next === undefined ||
467
+ next.startsWith("--")
468
+ ) {
456
469
  flags[name] = true;
457
470
  } else {
458
471
  setFlag(name, next);
@@ -671,6 +684,12 @@ Reviewers:
671
684
  automate send <event-name> --title <what happened> [--key <id>] [--url <u>] [--fact k=v ...]
672
685
  [--email <e>] [--person <name>] [--company <c>]
673
686
  Send an event from your own systems
687
+ automate findings [--state new|acted|dismissed|expired] [--automation <id>] [--site <host>] [--page <url>]
688
+ [--limit <n>] [--cursor <t>]
689
+ What the automations noticed: evidence, what it's about,
690
+ the button that acts on it, and how it ended
691
+ automate act <finding-id> Make the call a finding stores, as you
692
+ automate dismiss <finding-id> [--reason <why>] Set a finding aside
674
693
  automate remove <automation-id>
675
694
  reviewers invite <article-id> --email <e> [--name <n>]
676
695
  Invite a guest to review one post
@@ -1,6 +1,6 @@
1
1
  // `automate` — Letterpress → Automations (docs/architecture/event-automations.md): an event, read
2
2
  // against your filter (--instruction), then done by Letterpress as your prompt (--prompt) says.
3
- // options / list / show / add / set / try / runs / approve / reject / send / remove, through the
3
+ // options / list / show / add / set / try / runs / approve / reject / send / findings / act / dismiss / remove, through the
4
4
  // same tools the app uses. (A letterbase's writing automations are made and paced with `automations`.) `list` also
5
5
  // shows the jobs Letter runs for the account (source "letter": internal links, the blog's sync, the site's re-audit,
6
6
  // Fix autopilot, add-your-name suggestions, Auto-Plan, and each letterbase's writing automations), each with its
@@ -34,6 +34,7 @@ const TEMPLATES = [
34
34
  ];
35
35
  const UNITS = ["hours", "days", "weeks", "months"];
36
36
  const STATUSES = ["pending", "proposed", "acting", "acted", "answered", "skipped", "failed", "rejected"];
37
+ const FINDING_STATES = ["new", "acted", "dismissed", "expired"];
37
38
 
38
39
  const triggerParams = {
39
40
  object: {
@@ -164,6 +165,29 @@ export const ARGS = {
164
165
  decision: { internal: "approve or reject, from the subcommand" },
165
166
  reason: { flag: "reason" },
166
167
  },
168
+ // What the automations noticed (docs/architecture/automation-findings.md): read, act on, dismiss.
169
+ list_findings: {
170
+ automation_id: { flag: "automation" },
171
+ state: { flag: "state", enum: FINDING_STATES },
172
+ about: {
173
+ object: {
174
+ host: { flag: "site" },
175
+ page_url: { flag: "page" },
176
+ collection_id: { flag: "letterbase" },
177
+ question: { flag: "question" },
178
+ target_id: { flag: "target" },
179
+ },
180
+ },
181
+ limit: { flag: "limit", type: "num" },
182
+ cursor: { flag: "cursor" },
183
+ },
184
+ act_on_finding: {
185
+ finding_id: { positional: 0, label: "finding-id", required: true },
186
+ },
187
+ dismiss_finding: {
188
+ finding_id: { positional: 0, label: "finding-id", required: true },
189
+ reason: { flag: "reason" },
190
+ },
167
191
  send_automation_event: {
168
192
  event: { positional: 0, label: "event-name", required: true },
169
193
  key: { flag: "key" },
@@ -207,12 +231,18 @@ export async function cmdAutomate(ctx) {
207
231
  return run(rest, "decide_automation_run", "Rejected.", { decision: "reject" });
208
232
  case "send":
209
233
  return run(rest, "send_automation_event");
234
+ case "findings":
235
+ return run(rest, "list_findings");
236
+ case "act":
237
+ return run(rest, "act_on_finding", "Done.");
238
+ case "dismiss":
239
+ return run(rest, "dismiss_finding", "Dismissed.");
210
240
  case "remove":
211
241
  case "rm":
212
242
  return run(rest, "delete_event_automation", "Removed.");
213
243
  default:
214
244
  throw new CliError(
215
- `Unknown automate subcommand: ${sub ?? "(none)"}. Try: options, list, show, add, set, try, runs, approve, reject, send, remove`
245
+ `Unknown automate subcommand: ${sub ?? "(none)"}. Try: options, list, show, add, set, try, runs, approve, reject, send, findings, act, dismiss, remove`
216
246
  );
217
247
  }
218
248
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.176.79",
3
+ "version": "0.176.81",
4
4
  "description": "Spin up and manage Letter phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",