@audienti/cli 0.1.25 → 0.1.27

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/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@ All notable changes to the Audienti CLI are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.27] - 2026-07-22
8
+
9
+ ### Added
10
+
11
+ - Add `audienti operator failed-drafts` and `audienti operator failed-drafts requeue` for listing failed prospect operator drafts and queueing async rewrites.
12
+
13
+ ### Fixed
14
+
15
+ - Show prospect replan coach errors as not persisted instead of displaying failed `--apply` runs as dry runs.
16
+
17
+ ## [0.1.26] - 2026-07-22
18
+
19
+ ### Added
20
+
21
+ - Add `audienti prospects replan <prsp_id> [--apply]` for dry-running or persisting refreshed next-action coach plans.
22
+
7
23
  ## [0.1.25] - 2026-07-22
8
24
 
9
25
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audienti/cli",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Agent-first command-line client for Audienti.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api-client.js CHANGED
@@ -366,6 +366,13 @@ export class AudientiClient {
366
366
  return this.requestJson(accountPath(accountId, ["prospects", prospectId]));
367
367
  }
368
368
 
369
+ replanProspect(accountId, prospectId, body = {}) {
370
+ return this.requestJson(accountPath(accountId, ["prospects", prospectId, "replan"]), {
371
+ method: "POST",
372
+ body
373
+ });
374
+ }
375
+
369
376
  assignProspects(accountId, body) {
370
377
  return this.requestJson(accountPath(accountId, ["prospects", "assign"]), {
371
378
  method: "POST",
@@ -500,6 +507,13 @@ export class AudientiClient {
500
507
  return this.requestJson(accountPath(accountId, ["operator", "next"], query));
501
508
  }
502
509
 
510
+ requeueOperatorFailedDrafts(accountId, body = {}) {
511
+ return this.requestJson(accountPath(accountId, ["operator", "failed_drafts", "requeue"]), {
512
+ method: "POST",
513
+ body
514
+ });
515
+ }
516
+
503
517
  operatorOutcome(accountId, body) {
504
518
  return this.requestJson(accountPath(accountId, ["operator", "outcome"]), {
505
519
  method: "POST",
package/src/cli.js CHANGED
@@ -38,6 +38,7 @@ const PROSPECTS_ADD_PROFILE_USAGE = "Usage: audienti prospects add-profile <prsp
38
38
  const PROSPECTS_REPORT_BAD_PROFILE_USAGE = "Usage: audienti prospects report-bad-profile <prsp_id> <prof_id|citation_id> [--json] [--account <acct_id>]";
39
39
  const PROSPECTS_ASSIGN_USAGE = "Usage: audienti prospects assign <prsp_id> [prsp_id...] --assigned-user <id|me|unassign> [--json] [--account <acct_id>]";
40
40
  const PROSPECTS_SET_STATUS_USAGE = "Usage: audienti prospects set-status <prsp_id> --status <active|nurture|non_responsive|not_fit|bad_data_404|rejected> [--json] [--account <acct_id>]";
41
+ const PROSPECTS_REPLAN_USAGE = "Usage: audienti prospects replan <prsp_id> [--apply] [--json] [--account <acct_id>]";
41
42
  const PROSPECTS_REJECT_USAGE = "Usage: audienti prospects reject <prsp_id> [--json] [--account <acct_id>]";
42
43
  const PROSPECTS_NURTURE_USAGE = "Usage: audienti prospects nurture <prsp_id> [--reason <nurture|non_responsive|not_fit|bad_data_404>] [--json] [--account <acct_id>]";
43
44
  const PROSPECTS_RESTORE_USAGE = "Usage: audienti prospects restore <prsp_id> [--json] [--account <acct_id>]";
@@ -45,6 +46,8 @@ const PROSPECTS_LOCK_USAGE = "Usage: audienti prospects lock <prsp_id> [--note <
45
46
  const PROSPECTS_UNLOCK_USAGE = "Usage: audienti prospects unlock <prsp_id> [--json] [--account <acct_id>]";
46
47
  const PROSPECTS_CHECK_USAGE = "Usage: audienti prospects check [--json|--csv] [filters] [--account <acct_id>]";
47
48
  const PROSPECTS_IMPORT_BATCH_USAGE = "Usage: audienti prospects import-batch --file <csv|jsonl|json> [--list <list_id>] [--motion <motn_id>] [--assigned-user <id|me>] [--json] [--account <acct_id>]";
49
+ const OPERATOR_FAILED_DRAFTS_USAGE = "Usage: audienti operator failed-drafts [--json] [filters] [--account <acct_id>]";
50
+ const OPERATOR_FAILED_DRAFTS_REQUEUE_USAGE = "Usage: audienti operator failed-drafts requeue (--all | <row_id> [row_id...]) [--limit <n>] [--json] [filters] [--account <acct_id>]";
48
51
  const DNC_ADD_USAGE = "Usage: audienti dnc add <email|citation_id|profile_url> [--json] [--account <acct_id>]";
49
52
  const DNC_IMPORT_USAGE = "Usage: audienti dnc import --file <txt|csv> [--json] [--account <acct_id>]";
50
53
  const DNC_REMOVE_USAGE = "Usage: audienti dnc remove <dnc_entry_id> [--json] [--account <acct_id>]";
@@ -243,6 +246,7 @@ async function dispatch(argv, context) {
243
246
  if (normalizedResource === "prospects" && action === "show") return prospectsShow(rest, context, { accountOverride });
244
247
  if (normalizedResource === "prospects" && action === "assign") return prospectsAssign(rest, context, { accountOverride });
245
248
  if (normalizedResource === "prospects" && action === "set-status") return prospectsSetStatus(rest, context, { accountOverride });
249
+ if (normalizedResource === "prospects" && action === "replan") return prospectsReplan(rest, context, { accountOverride });
246
250
  if (normalizedResource === "prospects" && action === "reject") return prospectsDisposition("reject", rest, context, { accountOverride });
247
251
  if (normalizedResource === "prospects" && action === "nurture") return prospectsDisposition("nurture", rest, context, { accountOverride });
248
252
  if (normalizedResource === "prospects" && action === "restore") return prospectsDisposition("restore", rest, context, { accountOverride });
@@ -264,6 +268,7 @@ async function dispatch(argv, context) {
264
268
  if (normalizedResource === "tools" && action === "list") return toolsList(rest, context);
265
269
  if (normalizedResource === "tools" && action === "get") return toolsGet(rest, context, { accountOverride });
266
270
  if (normalizedResource === "tools" && action === "linkedin-review") return toolsLinkedinReview(rest, context, { accountOverride });
271
+ if (normalizedResource === "operator" && action === "failed-drafts") return operatorFailedDrafts(rest, context, { accountOverride });
267
272
  if (normalizedResource === "operator" && action === "queue") return operatorQueue(rest, context, { accountOverride });
268
273
  if (normalizedResource === "operator" && action === "next") return operatorNext(rest, context, { accountOverride });
269
274
  if (normalizedResource === "operator" && action === "outcome") return operatorOutcome(rest, context, { accountOverride });
@@ -1840,6 +1845,22 @@ async function prospectsShow(args, context, { accountOverride } = {}) {
1840
1845
  renderProspect(prospect, context);
1841
1846
  }
1842
1847
 
1848
+ async function prospectsReplan(args, context, { accountOverride } = {}) {
1849
+ const { values, positionals } = parseCommandArgs(args, {
1850
+ ...jsonOptions(),
1851
+ apply: { type: "boolean" }
1852
+ });
1853
+ if (positionals.length !== 1) throw new CommandError(PROSPECTS_REPLAN_USAGE);
1854
+
1855
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
1856
+ const payload = await client.replanProspect(accountId, positionals[0], compactObject({
1857
+ apply: values.apply
1858
+ }));
1859
+ if (values.json) return writeJson(context.stdout, payload);
1860
+
1861
+ renderProspectReplan(payload, context);
1862
+ }
1863
+
1843
1864
  async function prospectsDisposition(action, args, context, { accountOverride } = {}) {
1844
1865
  const usageText = {
1845
1866
  reject: PROSPECTS_REJECT_USAGE,
@@ -2444,6 +2465,41 @@ async function operatorQueue(args, context, { accountOverride } = {}) {
2444
2465
  renderOperatorQueue(payload, context);
2445
2466
  }
2446
2467
 
2468
+ async function operatorFailedDrafts(args, context, { accountOverride } = {}) {
2469
+ if (args[0] === "requeue") {
2470
+ return operatorFailedDraftsRequeue(args.slice(1), context, { accountOverride });
2471
+ }
2472
+
2473
+ const { values, positionals } = parseCommandArgs(args, operatorFailedDraftOptions());
2474
+ if (positionals.length > 0) throw new CommandError(OPERATOR_FAILED_DRAFTS_USAGE);
2475
+
2476
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
2477
+ const payload = await client.operatorQueue(accountId, operatorFailedDraftQuery(values));
2478
+ if (values.json) return writeJson(context.stdout, payload);
2479
+
2480
+ renderOperatorFailedDrafts(payload, context);
2481
+ }
2482
+
2483
+ async function operatorFailedDraftsRequeue(args, context, { accountOverride } = {}) {
2484
+ const { values, positionals } = parseCommandArgs(args, operatorFailedDraftOptions({
2485
+ all: { type: "boolean" },
2486
+ limit: { type: "string" }
2487
+ }));
2488
+ if (values.all && positionals.length > 0) throw new CommandError("Choose either --all or row ids, not both.");
2489
+ if (!values.all && positionals.length === 0) throw new CommandError(OPERATOR_FAILED_DRAFTS_REQUEUE_USAGE);
2490
+
2491
+ const { client, accountId } = await requireAccountContext(context, { accountOverride });
2492
+ const payload = await client.requeueOperatorFailedDrafts(accountId, compactObject({
2493
+ ...operatorFailedDraftQuery(values),
2494
+ all: values.all || undefined,
2495
+ limit: values.limit,
2496
+ row_ids: positionals.length > 0 ? positionals : undefined
2497
+ }));
2498
+ if (values.json) return writeJson(context.stdout, payload);
2499
+
2500
+ renderOperatorFailedDraftRequeue(payload, context);
2501
+ }
2502
+
2447
2503
  async function operatorNext(args, context, { accountOverride } = {}) {
2448
2504
  const { values, positionals } = parseCommandArgs(args, operatorNextOptions());
2449
2505
  if (positionals.length > 0) throw new CommandError("Usage: audienti operator next [--json|--plan|--done|--skip|--fail|--return] [filters] [--note <text>] [--account <acct_id>]");
@@ -2705,6 +2761,18 @@ function operatorNextOptions() {
2705
2761
  });
2706
2762
  }
2707
2763
 
2764
+ function operatorFailedDraftOptions(extra = {}) {
2765
+ return {
2766
+ ...jsonOptions(),
2767
+ principal: { type: "string" },
2768
+ motion: { type: "string" },
2769
+ list: { type: "string" },
2770
+ stage: { type: "string" },
2771
+ query: { type: "string" },
2772
+ ...extra
2773
+ };
2774
+ }
2775
+
2708
2776
  function operatorQuery(values) {
2709
2777
  return compactObject({
2710
2778
  principal_account_user_id: values.principal,
@@ -2716,6 +2784,18 @@ function operatorQuery(values) {
2716
2784
  });
2717
2785
  }
2718
2786
 
2787
+ function operatorFailedDraftQuery(values) {
2788
+ return compactObject({
2789
+ principal_account_user_id: values.principal,
2790
+ motion_id: values.motion,
2791
+ list_id: values.list,
2792
+ stage: values.stage,
2793
+ query: values.query,
2794
+ opportunity_kind: "prospect",
2795
+ writing_status: "draft_failed"
2796
+ });
2797
+ }
2798
+
2719
2799
  function operatorNextOutcomeStatus(values) {
2720
2800
  const selected = [
2721
2801
  values.done ? "done" : null,
@@ -3901,6 +3981,40 @@ function renderProspect(prospect, context) {
3901
3981
  if (nextActionLabel(prospect?.queue)) writeLine(context.stdout, `Next action: ${nextActionLabel(prospect.queue)}`);
3902
3982
  }
3903
3983
 
3984
+ function renderProspectReplan(payload, context) {
3985
+ const prospect = payload?.prospect || {};
3986
+ const current = payload?.current || {};
3987
+ const replanned = payload?.replanned || {};
3988
+ const status = replanStatusLabel(payload);
3989
+
3990
+ writeLine(context.stdout, `Replan ${status} for ${display(prospect.display_name || prospect.name)} (${display(prospect.prefix_id)}).`);
3991
+ writeLine(context.stdout, `Changed: ${payload?.changed ? "yes" : "no"}`);
3992
+ if (payload?.reason_code) writeLine(context.stdout, `Reason: ${payload.reason_code}`);
3993
+ writeLine(context.stdout, `Current: ${formatCoachAction(current.next_action)}`);
3994
+ writeLine(context.stdout, `Replanned: ${formatCoachAction(replanned.next_action)}`);
3995
+ if (replanned.rationale) writeLine(context.stdout, `Rationale: ${replanned.rationale}`);
3996
+ if (replanned.guidance) writeLine(context.stdout, `Guidance: ${replanned.guidance}`);
3997
+ if (payload?.status === "dry_run") writeLine(context.stdout, "Run again with --apply to persist this plan.");
3998
+ if (payload?.status === "coach_error") writeLine(context.stdout, "The plan was not persisted. Fix the coach error and rerun with --apply.");
3999
+ }
4000
+
4001
+ function replanStatusLabel(payload) {
4002
+ if (payload?.status === "dry_run") return "dry run";
4003
+ if (payload?.status === "coach_error") return "coach error";
4004
+ if (payload?.status === "not_applied") return "not applied";
4005
+
4006
+ return payload?.applied ? "applied" : "dry run";
4007
+ }
4008
+
4009
+ function formatCoachAction(nextAction = {}) {
4010
+ const action = nextAction?.label || nextAction?.type || "none";
4011
+ const mode = nextAction?.request_mode || nextAction?.mode;
4012
+ const timing = nextAction?.timing?.mode;
4013
+ const details = compactText([mode, timing]).join(", ");
4014
+
4015
+ return details ? `${action} (${details})` : action;
4016
+ }
4017
+
3904
4018
  function renderProspectDisposition(payload, context, { action }) {
3905
4019
  const prospect = payload?.prospect || {};
3906
4020
  const accountProspect = payload?.account_prospect || {};
@@ -4597,6 +4711,87 @@ function renderOperatorOutcome(payload, context) {
4597
4711
  }
4598
4712
  }
4599
4713
 
4714
+ function renderOperatorFailedDrafts(payload, context) {
4715
+ const rows = Array.isArray(payload?.decision_queue) ? payload.decision_queue : [];
4716
+ if (rows.length === 0) {
4717
+ writeLine(context.stdout, "No failed operator drafts found.");
4718
+ return;
4719
+ }
4720
+
4721
+ writeLine(context.stdout, "Failed operator drafts");
4722
+ writeAlignedTable(context, ["ROW ID", "PROSPECT", "MOTION", "STATUS", "REASON", "DRAFT"], rows.map(operatorFailedDraftTableRow));
4723
+ writeLine(context.stdout, "");
4724
+ writeLine(context.stdout, `Shown: ${rows.length}`);
4725
+ writeLine(context.stdout, "Requeue: audienti operator failed-drafts requeue <row_id> [row_id...]");
4726
+ writeLine(context.stdout, "If a rewrite fails again, it remains in this list with the latest failure reason.");
4727
+ }
4728
+
4729
+ function renderOperatorFailedDraftRequeue(payload, context) {
4730
+ const metrics = payload?.metrics || {};
4731
+ const queued = Number(metrics.queued_count || 0);
4732
+ const skipped = Number(metrics.skipped_count || 0);
4733
+ const failed = Number(metrics.failed_count || 0);
4734
+ writeLine(context.stdout, `Queued draft rewrites: ${queued}`);
4735
+ if (skipped > 0) writeLine(context.stdout, `Skipped: ${skipped}`);
4736
+ if (failed > 0) writeLine(context.stdout, `Failed: ${failed}`);
4737
+
4738
+ writeOperatorFailedDraftRequeueDetails(context, "Queued", payload?.queued);
4739
+ writeOperatorFailedDraftRequeueDetails(context, "Skipped", payload?.skipped);
4740
+ writeOperatorFailedDraftRequeueDetails(context, "Failed", payload?.failed);
4741
+
4742
+ const message = payload?.message ||
4743
+ "Rewrites run asynchronously. Re-run `audienti operator failed-drafts` with the same filters to see drafts that still fail after rewriting.";
4744
+ writeLine(context.stdout, "");
4745
+ writeLine(context.stdout, message);
4746
+ }
4747
+
4748
+ function writeOperatorFailedDraftRequeueDetails(context, label, rows) {
4749
+ const list = Array.isArray(rows) ? rows : [];
4750
+ if (list.length === 0) return;
4751
+
4752
+ writeLine(context.stdout, "");
4753
+ writeLine(context.stdout, label);
4754
+ writeAlignedTable(context, ["ROW ID", "PROSPECT", "REASON", "DRAFT ID", "JOB ID"], list.map((row) => [
4755
+ display(row.row_id),
4756
+ display(row.prospect_name || row.prospect_id),
4757
+ display(row.reason),
4758
+ display(row.draft_id || row.source_draft_id),
4759
+ display(row.job_id)
4760
+ ]));
4761
+ }
4762
+
4763
+ function operatorFailedDraftTableRow(row) {
4764
+ const draft = row?.operator_draft || {};
4765
+ return [
4766
+ display(row?.id),
4767
+ operatorSubjectLabel(row),
4768
+ operatorMotionLabel(row),
4769
+ display(draft.status || draft.state),
4770
+ operatorFailedDraftReason(draft),
4771
+ operatorFailedDraftSnippet(draft)
4772
+ ];
4773
+ }
4774
+
4775
+ function operatorFailedDraftReason(draft) {
4776
+ const payload = draft?.payload || {};
4777
+ const codes = Array.isArray(payload.quality_codes) ? payload.quality_codes.filter(Boolean).join(",") : "";
4778
+ return display(
4779
+ codes ||
4780
+ payload.blank_reason ||
4781
+ payload.error ||
4782
+ payload.message ||
4783
+ payload.status ||
4784
+ draft?.status ||
4785
+ draft?.state,
4786
+ "-"
4787
+ );
4788
+ }
4789
+
4790
+ function operatorFailedDraftSnippet(draft) {
4791
+ const payload = draft?.payload || {};
4792
+ return truncateCliText(payload.subject || payload.body || payload.text || "", 64) || "-";
4793
+ }
4794
+
4600
4795
  function renderAnalyticsProspects(payload, context) {
4601
4796
  writeLine(context.stdout, `Prospect analytics (${analyticsWindowLabel(payload)})`);
4602
4797
  writeAnalyticsCohort(payload, context);
@@ -5379,6 +5574,7 @@ const HELP_TOPICS = new Map([
5379
5574
  " audienti prospects show <prsp_id>",
5380
5575
  " audienti prospects assign <prsp_id> --assigned-user <id|me|unassign>",
5381
5576
  " audienti prospects set-status <prsp_id> --status <active|nurture|non_responsive|not_fit|bad_data_404|rejected>",
5577
+ " audienti prospects replan <prsp_id> [--apply]",
5382
5578
  " audienti prospects lock <prsp_id> [--note <text>]",
5383
5579
  " audienti prospects reject <prsp_id>",
5384
5580
  " audienti prospects nurture <prsp_id> [--reason <reason>]",
@@ -5417,11 +5613,13 @@ const HELP_TOPICS = new Map([
5417
5613
  " audienti prospects write <prsp_id> --type <surface_key>",
5418
5614
  " audienti prospects sequence-export <prsp_id>",
5419
5615
  "",
5420
- " Operator queue",
5421
- " audienti operator next --plan",
5422
- " audienti operator next --done --note <text>",
5423
- " audienti operator queue",
5424
- "",
5616
+ " Operator queue",
5617
+ " audienti operator next --plan",
5618
+ " audienti operator next --done --note <text>",
5619
+ " audienti operator queue",
5620
+ " audienti operator failed-drafts",
5621
+ " audienti operator failed-drafts requeue <row_id>",
5622
+ "",
5425
5623
  " Analytics",
5426
5624
  " audienti analytics prospects --window 24h",
5427
5625
  " audienti analytics dashboard --play-tag <tag>",
@@ -6881,6 +7079,7 @@ const HELP_TOPICS = new Map([
6881
7079
  " audienti prospects show <prsp_id> [--json]",
6882
7080
  " audienti prospects assign <prsp_id> [prsp_id...] --assigned-user <id|me|unassign> [--json]",
6883
7081
  " audienti prospects set-status <prsp_id> --status <active|nurture|non_responsive|not_fit|bad_data_404|rejected> [--json]",
7082
+ " audienti prospects replan <prsp_id> [--apply] [--json]",
6884
7083
  " audienti prospects reject <prsp_id> [--json]",
6885
7084
  " audienti prospects nurture <prsp_id> [--reason <reason>] [--json]",
6886
7085
  " audienti prospects restore <prsp_id> [--json]",
@@ -7062,6 +7261,28 @@ const HELP_TOPICS = new Map([
7062
7261
  " GET /api/v1/accounts/:account_id/prospects/:id.json"
7063
7262
  ].join("\n")],
7064
7263
 
7264
+ ["prospects replan", [
7265
+ "Usage:",
7266
+ ` ${PROSPECTS_REPLAN_USAGE.slice("Usage: ".length)}`,
7267
+ "",
7268
+ "Status: implemented",
7269
+ "",
7270
+ "Purpose:",
7271
+ " Re-run the next-action coach for one account prospect from the CLI without adding a product UI button.",
7272
+ "",
7273
+ "Behavior:",
7274
+ " Defaults to a dry-run so operators can compare the cached plan with the current planner output.",
7275
+ " Pass --apply to persist the replanned AccountProspect coach payload.",
7276
+ "",
7277
+ "API:",
7278
+ " POST /api/v1/accounts/:account_id/prospects/:id/replan.json",
7279
+ "",
7280
+ "JSON body:",
7281
+ " {",
7282
+ " \"apply\": true",
7283
+ " }"
7284
+ ].join("\n")],
7285
+
7065
7286
  ["prospects reject", [
7066
7287
  "Usage:",
7067
7288
  ` ${PROSPECTS_REJECT_USAGE.slice("Usage: ".length)}`,
@@ -7682,9 +7903,11 @@ const HELP_TOPICS = new Map([
7682
7903
  "Usage:",
7683
7904
  " audienti operator next [--json|--plan|--done|--skip|--fail|--return]",
7684
7905
  " audienti operator queue [--json]",
7906
+ " audienti operator failed-drafts [--json]",
7907
+ " audienti operator failed-drafts requeue (--all | <row_id> [row_id...])",
7685
7908
  " audienti operator outcome <row_id> --payload <file.json>",
7686
7909
  "",
7687
- "Status: read commands and prospect next-move writeback implemented",
7910
+ "Status: read commands, failed draft requeue, and prospect next-move writeback implemented",
7688
7911
  "",
7689
7912
  "Filters:",
7690
7913
  " --principal <account_user_id>",
@@ -7742,6 +7965,37 @@ const HELP_TOPICS = new Map([
7742
7965
  " GET /api/v1/accounts/:account_id/operator.json"
7743
7966
  ].join("\n")],
7744
7967
 
7968
+ ["operator failed-drafts", [
7969
+ "Usage:",
7970
+ " audienti operator failed-drafts [--json] [filters] [--account <acct_id>]",
7971
+ " audienti operator failed-drafts requeue (--all | <row_id> [row_id...]) [--limit <n>] [--json] [filters] [--account <acct_id>]",
7972
+ "",
7973
+ "Status: implemented",
7974
+ "",
7975
+ "Purpose:",
7976
+ " Lists failed prospect operator drafts and queues selected drafts for rewriting.",
7977
+ "",
7978
+ "Filters:",
7979
+ " --principal <account_user_id>",
7980
+ " --motion <motn_id>",
7981
+ " --list <list_id>",
7982
+ " --stage <stage>",
7983
+ " --query <text>",
7984
+ "",
7985
+ "Output:",
7986
+ " Plain text: failed draft rows with status, reason, and draft snippet",
7987
+ " JSON list: standard operator queue payload forced to prospect draft_failed rows",
7988
+ " JSON requeue: { status, queued[], skipped[], failed[], metrics, message }",
7989
+ "",
7990
+ "Notes:",
7991
+ " Requeue is async. A queued response means the rewrite job was accepted, not that the draft passed.",
7992
+ " If a rewrite fails again, rerun the list command with the same filters to see the latest failure reason.",
7993
+ "",
7994
+ "API:",
7995
+ " GET /api/v1/accounts/:account_id/operator.json?opportunity_kind=prospect&writing_status=draft_failed",
7996
+ " POST /api/v1/accounts/:account_id/operator/failed_drafts/requeue.json"
7997
+ ].join("\n")],
7998
+
7745
7999
  ["operator outcome", [
7746
8000
  "Usage:",
7747
8001
  " audienti operator outcome <row_id> --payload <file.json> [--json] [--account <acct_id>]",
@@ -8008,11 +8262,13 @@ const HELP_TOPICS = new Map([
8008
8262
  " audienti lists add-prospects <list_id> <prsp_id> [prsp_id...]",
8009
8263
  " audienti motions add-prospects <motn_id> <prsp_id> [prsp_id...]",
8010
8264
  "",
8011
- "6. Work the operator queue",
8012
- " audienti operator next",
8013
- " audienti operator next --plan",
8014
- " audienti operator queue --json",
8015
- " audienti operator outcome <row_id> --payload <file.json>",
8265
+ "6. Work the operator queue",
8266
+ " audienti operator next",
8267
+ " audienti operator next --plan",
8268
+ " audienti operator queue --json",
8269
+ " audienti operator failed-drafts",
8270
+ " audienti operator failed-drafts requeue <row_id>",
8271
+ " audienti operator outcome <row_id> --payload <file.json>",
8016
8272
  "",
8017
8273
  "7. Inspect account analytics",
8018
8274
  " audienti users activity me --window 7d",