@letterstory/cli 0.128.2 → 0.129.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/lib/cli.mjs CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  } from "./commands.mjs";
63
63
 
64
64
  // Keep in sync with cli/package.json.
65
- export const VERSION = "0.128.2";
65
+ export const VERSION = "0.129.0";
66
66
 
67
67
  // Flags that never take a value. Listing them explicitly means `deploy get --json <id>`
68
68
  // can't accidentally swallow the id as --json's value. Every `type: "bool"` flag (and its
@@ -923,6 +923,7 @@ Admin (STAFF key — --staff-key / LETTERSTORY_STAFF_API_KEY; acts before an org
923
923
  | renewals [--days 90]
924
924
  | reach-outs [--day YYYY-MM-DD] [--fresh] the day's reach-outs, N of 5 (#crm-reminders' count)
925
925
  | track-record [--since YYYY-MM-DD] | at-risk | expansion-signals
926
+ | weekly-note the Monday retention note for the last full week
926
927
  | collections [--org-ids a,b | --account-stages won,active]
927
928
  | delivery-flags [--org-ids a,b | --account-stages won,active] [--include collections]
928
929
  | case <account-id> [--outcome <outcome-id>]
@@ -955,6 +956,8 @@ Admin (STAFF key — --staff-key / LETTERSTORY_STAFF_API_KEY; acts before an org
955
956
  next-product rule was right (rates show once
956
957
  15 outcomes and 90 days exist). At-risk and
957
958
  expansion signals show the closest past case.
959
+ Weekly note: the note #crm-opportunities
960
+ gets on Mondays (reads only).
958
961
  Onboard runs org → link → phantom sites →
959
962
  Slack channel → checklist → app invites →
960
963
  stage in one call (--site "" = infer the
@@ -14,7 +14,7 @@
14
14
  // The old names — evals, eval-add, eval-set, proposals, propose-eval, capture-eval, reject-eval — still work.)
15
15
  // admin evals scoreboard|cases|runs|run|triage|guard|retire … (fleet:read / tuning:experiment)
16
16
  // admin fleet-experiments list|articles|clients|mark|unmark|new|assign|assign-eligible|assign-orgs|spin-up|apply|start|stop|decide … (fleet:read / fleet:experiment)
17
- // admin crm import|capture|outreach|signals|record|signal|accounts|account|score|slack-channels|link-slack|white-glove|set-white-glove|churn|revenue|reach-outs|record-churn|draft-churn-reason|undo-churn|outcomes|record-outcome|renewals|track-record|at-risk|expansion-signals|collections|delivery-flags|case|onboard|onboarding|retry-onboarding|onboard-plan|payment-link … (crm:read / crm:write)
17
+ // admin crm import|capture|outreach|signals|record|signal|accounts|account|score|slack-channels|link-slack|white-glove|set-white-glove|churn|revenue|reach-outs|record-churn|draft-churn-reason|undo-churn|outcomes|record-outcome|renewals|track-record|weekly-note|at-risk|expansion-signals|collections|delivery-flags|case|onboard|onboarding|retry-onboarding|onboard-plan|payment-link … (crm:read / crm:write)
18
18
  // admin spend summary|reconcile|pnl|margin|pricing|entries|add|import|usage|remove|reference|stripe-sync|services|service … (spend:read / spend:write)
19
19
  // admin brand-detection <org-id> (fleet:read)
20
20
  // admin brand-detection <org-id> [--term t]... [--exact t]... [--exclude p]... [--note "…"] | --clear [--note "…"] (fleet:instrument)
@@ -3523,6 +3523,13 @@ async function cmdAdminCrm(ctx) {
3523
3523
  : `(nothing in the next ${r.days} days)`
3524
3524
  );
3525
3525
  }
3526
+ case "weekly-note": {
3527
+ // admin crm weekly-note — the Monday retention note for the last full ISO week (reads only; never posts).
3528
+ return out(
3529
+ await staffRequest(ctx, "GET", `${CRM}/weekly-note`),
3530
+ (r) => `${r.week.key} (${r.week.from} to ${r.week.to})\n\n${r.text}`
3531
+ );
3532
+ }
3526
3533
  case "track-record": {
3527
3534
  // admin crm track-record [--since YYYY-MM-DD] — how often each risk and next-product rule was right.
3528
3535
  const pct = (x) => (x == null ? "—" : `${Math.round(x * 100)}%`);
@@ -3690,7 +3697,7 @@ async function cmdAdminCrm(ctx) {
3690
3697
  }
3691
3698
  default:
3692
3699
  throw new CliError(
3693
- "Usage: admin crm import|capture|outreach|signals|record|signal|accounts|account|score|slack-channels|link-slack|white-glove|set-white-glove|churn|revenue|reach-outs|record-churn|draft-churn-reason|undo-churn|outcomes|record-outcome|renewals|track-record|at-risk|expansion-signals|collections|delivery-flags|case|onboard|onboarding|retry-onboarding|onboard-plan|payment-link … (see --help)"
3700
+ "Usage: admin crm import|capture|outreach|signals|record|signal|accounts|account|score|slack-channels|link-slack|white-glove|set-white-glove|churn|revenue|reach-outs|record-churn|draft-churn-reason|undo-churn|outcomes|record-outcome|renewals|track-record|weekly-note|at-risk|expansion-signals|collections|delivery-flags|case|onboard|onboarding|retry-onboarding|onboard-plan|payment-link … (see --help)"
3694
3701
  );
3695
3702
  }
3696
3703
  }
@@ -97,7 +97,12 @@ async function visitsList(ctx) {
97
97
  const { flags, io } = ctx;
98
98
  const result = await call(ctx, "visitors_get_agent_visits");
99
99
  printResult(io, flags, result, (r) => {
100
- const lines = [`${r.total} agent visits since ${r.since} (${r.verified} verified)`];
100
+ const verified = r.verified !== null && r.verified !== undefined ? ` (${r.verified} verified)` : "";
101
+ const lines = [`${r.total} agent visits since ${r.since}${verified}`];
102
+ if (r.source === "visitors" && r.baseline)
103
+ lines.push(
104
+ `Counted from ${r.baseline}, the site's move to its current traffic source${r.lettervisit_verified !== null ? `; LetterVisit verified ${r.lettervisit_verified} since then` : ""}.`
105
+ );
101
106
  const why = Object.entries(r.by_purpose ?? {})
102
107
  .filter(([, n]) => n > 0)
103
108
  .map(([p, n]) => `${PURPOSE_LABELS[p] ?? p} ${n}`);
@@ -105,7 +110,9 @@ async function visitsList(ctx) {
105
110
  if (r.agents?.length) {
106
111
  lines.push("", "Agents:");
107
112
  for (const a of r.agents)
108
- lines.push(` ${a.agent.padEnd(14)} ${String(a.total).padStart(6)} (${a.verified} verified)`);
113
+ lines.push(
114
+ ` ${a.agent.padEnd(22)} ${String(a.total).padStart(6)}${a.verified !== null && a.verified !== undefined ? ` (${a.verified} verified)` : ""}`
115
+ );
109
116
  }
110
117
  if (r.top_paths?.length) {
111
118
  lines.push("", "Most read:");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@letterstory/cli",
3
- "version": "0.128.2",
3
+ "version": "0.129.0",
4
4
  "description": "Spin up and manage Letterstory phantom blogs from your terminal.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",