@moda-ai/cli 1.55.23 → 1.55.25

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.
Files changed (40) hide show
  1. package/dist/{agent-f8a1kejk.js → agent-t7dxmpdq.js} +8 -8
  2. package/dist/{cli-9g8vz4sv.js → cli-0wr3483h.js} +1 -1
  3. package/dist/{cli-4f6jkrnm.js → cli-7xc585hc.js} +5 -5
  4. package/dist/{cli-wkmdw40s.js → cli-9btx12wp.js} +1 -1
  5. package/dist/{cli-4yarp5s1.js → cli-9hc5bg2r.js} +1 -1
  6. package/dist/{cli-cv3jt1ms.js → cli-dn91fb56.js} +10 -10
  7. package/dist/{cli-t3a6eknn.js → cli-dve50x7p.js} +233 -28
  8. package/dist/{cli-54zhv6cx.js → cli-m0045npe.js} +17 -14
  9. package/dist/{cli-s6tw1fje.js → cli-m805msp6.js} +210 -23
  10. package/dist/{cli-z3g07t65.js → cli-mebf5vtr.js} +5 -5
  11. package/dist/{cli-2cggp8ww.js → cli-qvg26twp.js} +5 -4
  12. package/dist/{cli-d2zews6c.js → cli-qycsmxev.js} +3 -3
  13. package/dist/cli.js +1292 -335
  14. package/dist/{doctor-snb87jvy.js → doctor-q21mr5ya.js} +8 -8
  15. package/dist/{fix-fr48gr0w.js → fix-0qdtdz5h.js} +6 -6
  16. package/dist/{harness-github-actions-cfkx9ty9.js → harness-github-actions-atc5bbkj.js} +5 -5
  17. package/dist/{harness-m63b6s0k.js → harness-vzy7n7ea.js} +5 -5
  18. package/dist/{index-nsaph4as.js → index-4b1ybz51.js} +17 -17
  19. package/dist/{production-intelligence-fwjh572m.js → production-intelligence-c8e0xw3n.js} +11 -11
  20. package/dist/{profile-commands-548ts402.js → profile-commands-6e2dgv72.js} +3 -3
  21. package/dist/prompt-source-mcp.js +5 -5
  22. package/dist/{prompts-p66y7wep.js → prompts-3h5jcjrw.js} +6 -6
  23. package/dist/{provision-r9fhrvpw.js → provision-q86phh4a.js} +5 -5
  24. package/dist/{registry-n7dsdxmg.js → registry-s2vdsfw8.js} +3 -3
  25. package/dist/{skills-c17gg69y.js → skills-vq3njc8a.js} +5 -5
  26. package/dist/{sync-bne90xvj.js → sync-hq9dpqpr.js} +7 -7
  27. package/package.json +1 -1
  28. package/skills/integration/index.json +2 -2
  29. package/skills/moda-cli/SKILL.md +35 -30
  30. package/skills/moda-cli/references/commands.md +22 -22
  31. package/skills/moda-cli/references/dashboard-parity.md +4 -4
  32. package/skills/moda-cli/references/detections.md +10 -10
  33. package/skills/moda-cli/references/feedback.md +2 -2
  34. package/skills/moda-cli/references/output-protocol.md +2 -2
  35. package/skills/moda-cli/references/production-intelligence.md +13 -12
  36. package/skills/moda-cli/references/prompts.md +6 -2
  37. package/skills/moda-cli/references/recipes.md +14 -14
  38. package/skills/moda-cli/references/search-and-traces.md +32 -32
  39. package/skills/moda-cli/references/signals-and-false-positives.md +29 -29
  40. package/skills/moda-cli/references/troubleshooting.md +4 -4
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  buildDoctorReport
3
- } from "./cli-z3g07t65.js";
4
- import"./cli-9g8vz4sv.js";
5
- import"./cli-s6tw1fje.js";
3
+ } from "./cli-mebf5vtr.js";
4
+ import"./cli-0wr3483h.js";
5
+ import"./cli-m805msp6.js";
6
6
  import"./cli-mm48br00.js";
7
7
  import {
8
8
  HARNESS_REPORT_APPROVAL_PATH,
@@ -14,18 +14,18 @@ import {
14
14
  readHarnessSyncState,
15
15
  summarizeHarness,
16
16
  validateHarnessReport
17
- } from "./cli-4f6jkrnm.js";
17
+ } from "./cli-7xc585hc.js";
18
18
  import"./cli-97fnztpy.js";
19
- import"./cli-2cggp8ww.js";
20
- import"./cli-cv3jt1ms.js";
21
- import"./cli-wkmdw40s.js";
19
+ import"./cli-qvg26twp.js";
20
+ import"./cli-dn91fb56.js";
21
+ import"./cli-9btx12wp.js";
22
22
  import {
23
23
  CliInputError,
24
24
  resolveApiKey,
25
25
  resolveIngestUrl,
26
26
  resolveModaBaseUrl,
27
27
  resolveTenantId
28
- } from "./cli-t3a6eknn.js";
28
+ } from "./cli-dve50x7p.js";
29
29
  import"./cli-0v6na3yp.js";
30
30
 
31
31
  // src/agent.ts
@@ -8,7 +8,7 @@ import {
8
8
  saveProfileConfig,
9
9
  secretFilePathFromRef,
10
10
  writeSecretJsonFile
11
- } from "./cli-t3a6eknn.js";
11
+ } from "./cli-dve50x7p.js";
12
12
  import {
13
13
  __require
14
14
  } from "./cli-0v6na3yp.js";
@@ -4,16 +4,16 @@ import {
4
4
  import {
5
5
  createCommandContext,
6
6
  stringOption
7
- } from "./cli-2cggp8ww.js";
7
+ } from "./cli-qvg26twp.js";
8
8
  import {
9
9
  assertFlags,
10
10
  assertPositionals,
11
11
  requireTenant
12
- } from "./cli-cv3jt1ms.js";
12
+ } from "./cli-dn91fb56.js";
13
13
  import {
14
14
  ApiError,
15
15
  callControlAPI
16
- } from "./cli-wkmdw40s.js";
16
+ } from "./cli-9btx12wp.js";
17
17
  import {
18
18
  CliInputError,
19
19
  CliInputRequiredError,
@@ -39,7 +39,7 @@ import {
39
39
  resolveModaBaseUrl,
40
40
  resolveTenantId,
41
41
  shouldInventoryFile
42
- } from "./cli-t3a6eknn.js";
42
+ } from "./cli-dve50x7p.js";
43
43
  import {
44
44
  __commonJS,
45
45
  __require,
@@ -195871,7 +195871,7 @@ async function runHarnessCommand(context) {
195871
195871
  throw new CliInputError("Focused remote prompt analysis is not supported yet.", "Use local --analyst=claude|codex|cursor|local-scan, or drop --concern for a full remote report.");
195872
195872
  }
195873
195873
  if (context.flags["github-actions"] === "true") {
195874
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-cfkx9ty9.js");
195874
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-atc5bbkj.js");
195875
195875
  const result = await runGithubActionsAnalyze(rootDir, {
195876
195876
  writeReport: (report2) => {
195877
195877
  const normalized = normalizeHarnessReport(report2);
@@ -3,7 +3,7 @@ import {
3
3
  recordApiRequest,
4
4
  resolveApiKey,
5
5
  resolveModaBaseUrl
6
- } from "./cli-t3a6eknn.js";
6
+ } from "./cli-dve50x7p.js";
7
7
 
8
8
  // src/api-client.ts
9
9
  var REQUEST_TIMEOUT_MS = 30000;
@@ -5,7 +5,7 @@ import {
5
5
  resolveApiKey,
6
6
  resolveApiKeyFromActiveProfile,
7
7
  resolveModaBaseUrl
8
- } from "./cli-t3a6eknn.js";
8
+ } from "./cli-dve50x7p.js";
9
9
 
10
10
  // src/api-key-auth.ts
11
11
  var PROBE_TIMEOUT_MS = 1e4;
@@ -2,7 +2,7 @@ import {
2
2
  ApiError,
3
3
  callControlAPI,
4
4
  callDataAPI
5
- } from "./cli-wkmdw40s.js";
5
+ } from "./cli-9btx12wp.js";
6
6
  import {
7
7
  CliAccessError,
8
8
  CliInputError,
@@ -11,7 +11,7 @@ import {
11
11
  resolveApiKey,
12
12
  resolveApiTenantId,
13
13
  setPlatformTenantOverride
14
- } from "./cli-t3a6eknn.js";
14
+ } from "./cli-dve50x7p.js";
15
15
 
16
16
  // src/schemas.ts
17
17
  import { z } from "zod";
@@ -209,7 +209,7 @@ var FalsePositiveSchema = z.object({
209
209
  conversation_id: z.string().min(1).max(255).optional().describe("Trace ID (required for problem-detection and custom-signal)"),
210
210
  attribution_id: z.string().regex(UUID_RE, "Attribution id must be a UUID").optional().describe("Detection UUID (required for problem-detection)"),
211
211
  family: z.string().regex(/^[a-z_]{1,64}$/, "Family must be a lowercase emotion family").optional().describe("Emotion family of the quote (quote kind)"),
212
- turn: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()).describe("Turn of the quote (quote kind; from moda emotions)"),
212
+ turn: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()).describe("Turn of the quote (quote kind; from moda detections list --family=emotion)"),
213
213
  quote: z.string().min(1).max(4000).optional().describe("The quoted user text (quote kind)"),
214
214
  tool: z.string().min(1).max(255).optional().describe("Failing tool name (tool kind)"),
215
215
  tool_use_id: z.string().min(1).max(255).optional().describe("Tool call id (tool kind; or pass --msg-index)"),
@@ -230,11 +230,11 @@ var FalsePositiveSchema = z.object({
230
230
  need(v.attribution_id, "--attribution-id is required for problem-detection");
231
231
  }
232
232
  if (v.kind === "quote") {
233
- need(v.family && v.turn !== undefined && v.quote, "--family, --turn and --quote are required for quote (copy them from moda emotions)");
233
+ need(v.family && v.turn !== undefined && v.quote, "--family, --turn and --quote are required for quote (copy them from moda detections list --family=emotion)");
234
234
  }
235
235
  if (v.kind === "tool") {
236
236
  need(v.tool, "--tool is required for tool (the failing tool name)");
237
- need(v.tool_use_id || v.msg_index !== undefined, "--tool-use-id or --msg-index is required for tool (from moda tool-failure-detail)");
237
+ need(v.tool_use_id || v.msg_index !== undefined, "--tool-use-id or --msg-index is required for tool (from moda detections tools)");
238
238
  }
239
239
  if (v.kind === "custom-signal") {
240
240
  need(v.conversation_id, "--conversation-id is required for custom-signal");
@@ -306,7 +306,7 @@ var TailSchema = z.object({
306
306
  full_scan: boolFlag().describe("Emotions: scan the whole window, not the top-scoring prefix (many more requests)")
307
307
  });
308
308
  var ToolFailureDetailSchema = z.object({
309
- tool_name: z.string().describe("Tool name (from moda tool-failures)"),
309
+ tool_name: z.string().describe("Tool name (from moda detections tools)"),
310
310
  subtype: z.string().optional().describe("Only this failure subtype"),
311
311
  days_back: daysBackFlag(7),
312
312
  limit: z.number().min(1).max(20).default(5).optional().describe("Maximum examples to return"),
@@ -497,7 +497,7 @@ var MISROUTE_WORDS = /attribut|misrout|false[\s_-]?positive|wrong[\s_-]?(?:probl
497
497
  function dedicatedCommandHint(category, rawCategory) {
498
498
  if (!MISROUTE_CATEGORIES.has(category) && !(rawCategory && MISROUTE_WORDS.test(rawCategory)))
499
499
  return;
500
- return "Feedback is read by the Moda team but does not change the problem. To act on it directly, use " + "`moda problem-feedback <problem_id> --action=flag_attribution --attribution-id=<uuid> --reason=TEXT` (a trace wrongly " + "attributed to a problem), `moda false-positive <kind> <target> --reason=TEXT` (a detection that should not " + "have fired), or `moda fix dismiss <fix_id> --reason=TEXT` (a fix aimed at the wrong problem).";
500
+ return "Feedback is read by the Moda team but does not change the problem. To act on it directly, use " + "`moda problems feedback <problem_id> --action=flag_attribution --attribution-id=<uuid> --reason=TEXT` (a trace wrongly " + "attributed to a problem), `moda review <kind> <target> --reason=TEXT` (a detection that should not " + "have fired), or `moda fix dismiss <fix_id> --reason=TEXT` (a fix aimed at the wrong problem).";
501
501
  }
502
502
 
503
503
  // src/command-flags.ts
@@ -998,9 +998,9 @@ async function runUserCommand(context) {
998
998
  }
999
999
  async function runProblemReopenCommand(context) {
1000
1000
  assertFlags("problem-reopen", context.flags, specFlagNames(COMMAND_FLAG_SPECS["problem-reopen"]));
1001
- assertPositionals("problem-reopen", context.positionals, 1, "moda problem-reopen <problem_id> [--reason=TEXT]");
1001
+ assertPositionals("problem-reopen", context.positionals, 1, "moda problems reopen <problem_id> [--reason=TEXT]");
1002
1002
  const problemId = context.positionals[0];
1003
- const usage = "Usage: moda problem-reopen <problem_id> [--reason=TEXT]";
1003
+ const usage = "Usage: moda problems reopen <problem_id> [--reason=TEXT]";
1004
1004
  if (!problemId || !UUID_RE2.test(problemId))
1005
1005
  throw new CliInputError("<problem_id> (UUID) is required.", usage);
1006
1006
  const reason = context.flags.reason;
@@ -1297,4 +1297,4 @@ function unknownSignalsSubcommandError(sub, args = []) {
1297
1297
  ${SIGNAL_USAGE}`);
1298
1298
  }
1299
1299
 
1300
- export { ProblemsRemainderSchema, UUID_RE, ProblemImpactSchema, PROBLEM_FEEDBACK_ACTIONS, ProblemFeedbackSchema, ProblemLinearFileSchema, SIGNAL_LABELS, SignalLabelSchema, DETECTION_VERDICTS, DetectionReviewSchema, FALSE_POSITIVE_KINDS, FalsePositiveSchema, StepScoresSchema, AuditSchema, FEEDBACK_USAGE, isFeedbackRefFlag, buildFeedbackRequest, COMMAND_FLAG_SPECS, flagSpecFor, kebabFlag, schemaShape, specFlagKeys, specFlagNames, describeSpecFlags, closestMatches, renderFlagHelp, subcommandHelpFlags, manifestFlagFields, requireTenant, assertFlags, assertPositionals, runUsersCommand, runUserCommand, runProblemReopenCommand, runSignalsManagementCommand, SIGNALS_MANAGEMENT_SUBCOMMANDS, unknownSignalsSubcommandError };
1300
+ export { ProblemsRemainderSchema, UUID_RE, ProblemImpactSchema, PROBLEM_FEEDBACK_ACTIONS, ProblemFeedbackSchema, ProblemLinearFileSchema, SignalLabelSchema, DETECTION_VERDICTS, DetectionReviewSchema, FALSE_POSITIVE_KINDS, FalsePositiveSchema, EMOTION_FAMILIES, LAZINESS_FAMILIES, StepScoresSchema, AuditSchema, FEEDBACK_USAGE, isFeedbackRefFlag, buildFeedbackRequest, COMMAND_FLAG_SPECS, flagSpecFor, kebabFlag, schemaShape, specFlagKeys, specFlagNames, describeSpecFlags, closestMatches, renderFlagHelp, subcommandHelpFlags, manifestFlagFields, requireTenant, assertFlags, assertPositionals, runUsersCommand, runUserCommand, runProblemReopenCommand, runSignalsManagementCommand, SIGNALS_MANAGEMENT_SUBCOMMANDS, unknownSignalsSubcommandError };
@@ -972,7 +972,7 @@ function trimToolFailureConversations(response, opts) {
972
972
  const msgIndex = asNumber(asRecord(row.anchor)?.msg_index) ?? asNumber(row.msg_index);
973
973
  return {
974
974
  ...rest,
975
- ...conversationId && msgIndex !== null ? { context_command: `moda context ${shellWord(contextTarget(conversationId))} --msg-index=${msgIndex} --window=${TOOL_FAILURE_CONTEXT_RADIUS}` } : {},
975
+ ...conversationId && msgIndex !== null ? { context_command: `moda traces get ${shellWord(contextTarget(conversationId))} --msg-index=${msgIndex} --window=${TOOL_FAILURE_CONTEXT_RADIUS}` } : {},
976
976
  ...opts.drop ? {} : { conversation: trimFailureWindow(conversation, TOOL_FAILURE_CONTEXT_RADIUS, msgIndex) },
977
977
  ..."window" in row ? { window: trimFailureWindow(window, opts.windowRadius ?? TOOL_FAILURE_CONTEXT_RADIUS, msgIndex) } : {}
978
978
  };
@@ -1019,7 +1019,7 @@ function withoutDetectionWindows(response, listKey, windowKey) {
1019
1019
  const msgIndex = asNumber(asRecord(row.anchor)?.msg_index) ?? frustrationAnchorIndex(row);
1020
1020
  return {
1021
1021
  ...rest,
1022
- ...conversationId && msgIndex !== null ? { context_command: `moda context ${shellWord(contextTarget(conversationId))} --msg-index=${msgIndex} --window=${DETECTION_CONTEXT_RADIUS}` } : {}
1022
+ ...conversationId && msgIndex !== null ? { context_command: `moda traces get ${shellWord(contextTarget(conversationId))} --msg-index=${msgIndex} --window=${DETECTION_CONTEXT_RADIUS}` } : {}
1023
1023
  };
1024
1024
  });
1025
1025
  return { ...response, [listKey]: rows };
@@ -1057,7 +1057,7 @@ function compactProblemDossier(response, problemId) {
1057
1057
  causal_rationale: row.causal_rationale ?? null,
1058
1058
  door: row.door ?? null,
1059
1059
  replay_verified: row.replay_verified ?? null,
1060
- ...conversationId && msgIndex !== null ? { context_command: `moda context ${shellWord(contextTarget(conversationId))} --msg-index=${msgIndex}` } : {}
1060
+ ...conversationId && msgIndex !== null ? { context_command: `moda traces get ${shellWord(contextTarget(conversationId))} --msg-index=${msgIndex}` } : {}
1061
1061
  };
1062
1062
  });
1063
1063
  const reportsBlock = asRecord(response.investigation_reports);
@@ -1095,13 +1095,13 @@ function compactProblemDossier(response, problemId) {
1095
1095
  reports_has_more: reportsBlock?.has_more === true,
1096
1096
  blocks: PROBLEM_COMPACT_OMITTED_BLOCKS.filter((key) => (key in response))
1097
1097
  },
1098
- full_command: `moda problem ${id} --full`
1098
+ full_command: `moda problems get ${id} --full`
1099
1099
  };
1100
1100
  const nextCommands = [
1101
- readCommand(`moda problem ${id} --evidence --limit=20`, "Page every evidence row with its anchor (follow next_cursor)."),
1102
- readCommand(`moda problem ${id} --reports`, "Page investigation reports with narratives and citations."),
1103
- readCommand(`moda problem ${id} --traces`, "Page affected traces with their latest anchor."),
1104
- readCommand(`moda problem ${id} --full`, "The complete dossier, every block (large).")
1101
+ readCommand(`moda problems get ${id} --evidence --limit=20`, "Page every evidence row with its anchor (follow next_cursor)."),
1102
+ readCommand(`moda problems get ${id} --reports`, "Page investigation reports with narratives and citations."),
1103
+ readCommand(`moda problems get ${id} --traces`, "Page affected traces with their latest anchor."),
1104
+ readCommand(`moda problems get ${id} --full`, "The complete dossier, every block (large).")
1105
1105
  ];
1106
1106
  const first = topEvidence.find((row) => typeof row.context_command === "string");
1107
1107
  if (first?.context_command) {
@@ -1450,11 +1450,206 @@ function packSnapshot(inputs, opts) {
1450
1450
  skips
1451
1451
  };
1452
1452
  }
1453
+ // src/legacy-names.ts
1454
+ var LEGACY_NAMES = [
1455
+ { legacy: "conversations", use: "moda traces list", canonical: { command: "traces", subcommand: "list" }, silent: true },
1456
+ { legacy: "search", use: 'moda traces search "<query>"', canonical: { command: "traces", subcommand: "search" } },
1457
+ { legacy: "context", use: "moda traces get <conversation_id>", canonical: { command: "traces", subcommand: "get" } },
1458
+ { legacy: "world-state", use: "moda traces state <conversation_id>", canonical: { command: "traces", subcommand: "state" } },
1459
+ { legacy: "audit", use: "moda traces spans <conversation_id|trace_id>", canonical: { command: "traces", subcommand: "spans" } },
1460
+ { legacy: "trace", use: "moda traces spans <conversation_id|trace_id>", canonical: { command: "traces", subcommand: "spans" } },
1461
+ { legacy: "problem", use: "moda problems get <problem_id>", canonical: { command: "problems", subcommand: "get" } },
1462
+ { legacy: "problems remainder", use: "moda problems unexplained", canonical: { command: "problems", subcommand: "unexplained" } },
1463
+ { legacy: "problem-impact", use: "moda problems impact", canonical: { command: "problems", subcommand: "impact" } },
1464
+ { legacy: "problem-feedback", use: "moda problems feedback <problem_id>", canonical: { command: "problems", subcommand: "feedback" } },
1465
+ { legacy: "problem-reopen", use: "moda problems reopen <problem_id>", canonical: { command: "problems", subcommand: "reopen" } },
1466
+ { legacy: "problem-linear", use: "moda problems linear <problem_id>", canonical: { command: "problems", subcommand: "linear" } },
1467
+ { legacy: "problem-linear-file", use: "moda problems link <problem_id>", canonical: { command: "problems", subcommand: "link" } },
1468
+ { legacy: "emotions", use: "moda detections list --family=emotion[:<family>]", canonical: { command: "detections", subcommand: "list" } },
1469
+ { legacy: "frustrations", use: "moda detections list --family=frustration", canonical: { command: "detections", subcommand: "list" } },
1470
+ { legacy: "laziness", use: "moda detections list --family=laziness[:<family>]", canonical: { command: "detections", subcommand: "list" } },
1471
+ { legacy: "hallucinations", use: "moda detections list --family=hallucination", canonical: { command: "detections", subcommand: "list" } },
1472
+ { legacy: "tool-failures", use: "moda detections tools", canonical: { command: "detections", subcommand: "tools" } },
1473
+ { legacy: "tool-failure-detail", use: "moda detections tools <tool_name>", canonical: { command: "detections", subcommand: "tools" } },
1474
+ { legacy: "signal --detections", use: "moda detections list --family=custom_signal --signal-id=<signal_id>", canonical: { command: "detections", subcommand: "list" } },
1475
+ { legacy: "trace-signals", use: "moda detections list --family=custom_signal --conversation-id=<conversation_id>", canonical: { command: "detections", subcommand: "list" } },
1476
+ { legacy: "false-positive", use: "moda review <kind> <target>", canonical: { command: "review" } },
1477
+ { legacy: "detection-review", use: "moda review problem-detection <problem_id> --verdict=<verdict>", canonical: { command: "review", subcommand: "problem-detection" } },
1478
+ { legacy: "signal-label", use: "moda review custom-signal <signal_id> --verdict=correct|false_positive", canonical: { command: "review", subcommand: "custom-signal" } },
1479
+ { legacy: "false-positives", use: "moda reviews list", canonical: { command: "reviews", subcommand: "list" } },
1480
+ { legacy: "detection-reviews", use: "moda reviews list <conversation_id> --kind=problem-detection", canonical: { command: "reviews", subcommand: "list" } },
1481
+ { legacy: "skills sync", use: "moda skills push", canonical: { command: "skills", subcommand: "push" }, note: "It uploads local SKILL.md files ('moda sync skills' downloads; that is 'moda skills pull')." },
1482
+ { legacy: "sync skills", use: "moda skills pull", canonical: { command: "skills", subcommand: "pull" }, note: "It downloads skills, while 'moda skills sync' uploads; use 'moda skills pull' (download) or 'moda skills push' (upload)." }
1483
+ ];
1484
+ var byLegacy = new Map(LEGACY_NAMES.map((entry) => [entry.legacy, entry]));
1485
+ var LEGACY_PATTERN = new RegExp(`moda (${[...LEGACY_NAMES.map((entry) => entry.legacy.replace(/ --detections$/, "")), "signal"].filter((name, index, all) => all.indexOf(name) === index).sort((left, right) => right.length - left.length).map((name) => name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})(?![\\w-])`, "g");
1486
+ var WORD = /(?:'[^']*'|"(?:[^"\\]|\\.)*"|\\.|[^\s'"]|['"])+/g;
1487
+ function commandEnd(text, from, opener) {
1488
+ let quote = "";
1489
+ for (let index = from;index < text.length; index += 1) {
1490
+ const char = text[index];
1491
+ const next = text[index + 1] ?? "";
1492
+ if (char === `
1493
+ ` || char === "`")
1494
+ return index;
1495
+ if ((opener === '"' || opener === "'") && char === opener && !quote)
1496
+ return index;
1497
+ if (char === '"' || char === "'") {
1498
+ if (!quote)
1499
+ quote = char;
1500
+ else if (quote === char)
1501
+ quote = "";
1502
+ continue;
1503
+ }
1504
+ if (quote)
1505
+ continue;
1506
+ if (opener === "(" && char === ")")
1507
+ return index;
1508
+ if (char === "|" || char === ";")
1509
+ return index;
1510
+ if ((char === "," || char === ".") && (next === " " || next === ""))
1511
+ return index;
1512
+ if (char === " " && (next === "(" || next === "#" || text.startsWith("moda ", index + 1) || text.startsWith("&&", index + 1)))
1513
+ return index;
1514
+ }
1515
+ return text.length;
1516
+ }
1517
+ function isPlaceholder(token) {
1518
+ return /^"?<[^>]+>"?$/.test(token);
1519
+ }
1520
+ function quotedArgumentSpans(text) {
1521
+ const spans = [];
1522
+ for (const match of text.matchAll(/moda (?=[a-z])/g)) {
1523
+ const start = match.index ?? 0;
1524
+ if (spans.some(([from, to]) => start > from && start < to))
1525
+ continue;
1526
+ const end = commandEnd(text, start + match[0].length, start > 0 ? text[start - 1] : "");
1527
+ let open = -1;
1528
+ for (let index = start;index < end; index += 1) {
1529
+ const char = text[index];
1530
+ if (char !== '"' && char !== "'")
1531
+ continue;
1532
+ if (open === -1)
1533
+ open = index;
1534
+ else if (text[open] === char) {
1535
+ spans.push([open, index]);
1536
+ open = -1;
1537
+ }
1538
+ }
1539
+ if (open !== -1)
1540
+ spans.push([open, end]);
1541
+ }
1542
+ return spans;
1543
+ }
1544
+ function canonicalInvocation(entry, rest) {
1545
+ let words = [...rest];
1546
+ const takeFlag = (pattern) => {
1547
+ const index = words.findIndex((word2) => pattern.test(word2));
1548
+ if (index === -1)
1549
+ return;
1550
+ const [word] = words.splice(index, 1);
1551
+ return word;
1552
+ };
1553
+ let familySuffix = "";
1554
+ switch (entry.legacy) {
1555
+ case "emotions":
1556
+ case "laziness": {
1557
+ const family = takeFlag(/^--family=/);
1558
+ if (family)
1559
+ familySuffix = `:${family.slice("--family=".length)}`;
1560
+ break;
1561
+ }
1562
+ case "signal --detections":
1563
+ takeFlag(/^--detections(=true)?$/);
1564
+ break;
1565
+ case "false-positive":
1566
+ words = words.map((word) => /^--undo(=true)?$/.test(word) ? "--verdict=clear" : word);
1567
+ break;
1568
+ case "signal-label":
1569
+ words = words.map((word) => word.replace(/^--label=fits$/, "--verdict=correct").replace(/^--label=does_not_fit$/, "--verdict=false_positive").replace(/^--label=.*$/, "--verdict=correct|false_positive"));
1570
+ break;
1571
+ default:
1572
+ break;
1573
+ }
1574
+ const positionals = [];
1575
+ while (words.length > 0 && !words[0].startsWith("-"))
1576
+ positionals.push(words.shift());
1577
+ const out = [];
1578
+ for (const token of entry.use.replace(/\[[^\]]*\]/g, "").split(" ")) {
1579
+ const flag = /^(--[a-z-]+=)(.*)$/.exec(token);
1580
+ if (isPlaceholder(token) || flag && isPlaceholder(flag[2])) {
1581
+ const value = positionals.shift();
1582
+ if (value !== undefined)
1583
+ out.push(flag ? `${flag[1]}${value}` : value);
1584
+ } else if (token.includes("|")) {} else {
1585
+ out.push(token.startsWith("--family=") ? `${token}${familySuffix}` : token);
1586
+ }
1587
+ }
1588
+ return [...out, ...positionals, ...words].join(" ");
1589
+ }
1590
+ function canonicalCommandText(text) {
1591
+ if (!text.includes("moda "))
1592
+ return text;
1593
+ const quoted = quotedArgumentSpans(text);
1594
+ let out = "";
1595
+ let cursor = 0;
1596
+ for (const match of text.matchAll(LEGACY_PATTERN)) {
1597
+ const start = match.index ?? 0;
1598
+ if (start < cursor)
1599
+ continue;
1600
+ if (quoted.some(([from, to]) => start > from && start < to))
1601
+ continue;
1602
+ const afterName = start + match[0].length;
1603
+ const end = text[afterName] === " " ? commandEnd(text, afterName, start > 0 ? text[start - 1] : "") : afterName;
1604
+ const rest = text.slice(afterName, end).match(WORD) ?? [];
1605
+ const name = match[1];
1606
+ const entry = name === "signal" ? rest.some((word) => /^--detections(=true)?$/.test(word)) ? byLegacy.get("signal --detections") : undefined : byLegacy.get(name);
1607
+ if (!entry)
1608
+ continue;
1609
+ out += `${text.slice(cursor, start)}${canonicalInvocation(entry, rest)}`;
1610
+ const trailing = /\s*$/.exec(text.slice(afterName, end))?.[0] ?? "";
1611
+ out += trailing;
1612
+ cursor = end;
1613
+ }
1614
+ return out + text.slice(cursor);
1615
+ }
1616
+
1453
1617
  // src/output.ts
1454
1618
  import { randomUUID } from "node:crypto";
1455
1619
  import { lstatSync, mkdirSync as mkdirSync2, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
1456
1620
  import { tmpdir } from "node:os";
1457
1621
  import { join as join2 } from "node:path";
1622
+ var SUGGESTION_KEY = /(_commands?|^hints?|^suggestions?)$/i;
1623
+ function canonicalDeep(value, rewriteStrings) {
1624
+ if (typeof value === "string")
1625
+ return rewriteStrings ? canonicalCommandText(value) : value;
1626
+ if (Array.isArray(value)) {
1627
+ let changed2 = false;
1628
+ const next = value.map((item) => {
1629
+ const rewritten = canonicalDeep(item, rewriteStrings);
1630
+ if (rewritten !== item)
1631
+ changed2 = true;
1632
+ return rewritten;
1633
+ });
1634
+ return changed2 ? next : value;
1635
+ }
1636
+ if (value === null || typeof value !== "object")
1637
+ return value;
1638
+ let changed = false;
1639
+ const entries = Object.entries(value).map(([key, entry]) => {
1640
+ const rewritten = canonicalDeep(entry, rewriteStrings || SUGGESTION_KEY.test(key));
1641
+ if (rewritten !== entry)
1642
+ changed = true;
1643
+ return [key, rewritten];
1644
+ });
1645
+ return changed ? Object.fromEntries(entries) : value;
1646
+ }
1647
+ function canonicalSuggestionFields(value) {
1648
+ return canonicalDeep(value, false);
1649
+ }
1650
+ function canonicalSuggestions(value) {
1651
+ return canonicalDeep(value, true);
1652
+ }
1458
1653
  var agentUpdateNotice;
1459
1654
  function setAgentUpdateNotice(notice) {
1460
1655
  agentUpdateNotice = notice;
@@ -1608,6 +1803,8 @@ function resolveOutputMode(flags, opts = {}) {
1608
1803
  return "human";
1609
1804
  }
1610
1805
  function createCliOutput(options) {
1806
+ const deprecatedMeta = options.deprecation ? { deprecated: { legacy: options.deprecation.legacy, use: options.deprecation.use } } : {};
1807
+ const deprecationWarnings = options.deprecation ? [options.deprecation.message] : [];
1611
1808
  const state = {
1612
1809
  runId: options.runId ?? randomUUID(),
1613
1810
  seq: 0,
@@ -1657,6 +1854,7 @@ function createCliOutput(options) {
1657
1854
  data,
1658
1855
  meta: {
1659
1856
  ...writeOptions.meta ?? {},
1857
+ ...deprecatedMeta,
1660
1858
  run_id: state.runId,
1661
1859
  ...options.command === "feedback" ? {} : { tip: FEEDBACK_TIP },
1662
1860
  ...((update) => update ? { update } : {})(resolveAgentUpdateNotice())
@@ -1668,6 +1866,7 @@ function createCliOutput(options) {
1668
1866
  nextCommands: writeOptions.nextCommands,
1669
1867
  artifacts: writeOptions.artifacts,
1670
1868
  warnings: writeOptions.warnings,
1869
+ extraWarnings: deprecationWarnings,
1671
1870
  errors: writeOptions.errors,
1672
1871
  invocation: options.invocation
1673
1872
  });
@@ -1706,10 +1905,10 @@ function createCliOutput(options) {
1706
1905
  }
1707
1906
  return;
1708
1907
  }
1709
- safeWriteStdout(`${JSON.stringify(redactDeep(data), null, 2)}
1908
+ safeWriteStdout(`${JSON.stringify(canonicalSuggestionFields(redactDeep(data)), null, 2)}
1710
1909
  `);
1711
1910
  for (const warning of writeOptions.warnings ?? []) {
1712
- safeWriteStderr(`Warning: ${warning}
1911
+ safeWriteStderr(`Warning: ${canonicalCommandText(warning)}
1713
1912
  `);
1714
1913
  }
1715
1914
  },
@@ -1718,6 +1917,7 @@ function createCliOutput(options) {
1718
1917
  return;
1719
1918
  if (options.mode !== "agent-stream")
1720
1919
  return;
1920
+ event = canonicalSuggestions(event);
1721
1921
  if (event.event === "started") {
1722
1922
  startHeartbeat(options.command, state);
1723
1923
  emitEvent(event);
@@ -1729,8 +1929,8 @@ function createCliOutput(options) {
1729
1929
  writeError(error) {
1730
1930
  if (state.terminal)
1731
1931
  return;
1732
- const agentError = errorToAgentError(error);
1733
- const envelope = createAgentErrorEnvelope(options.command || "unknown", agentError, state.runId, errorWarnings(error));
1932
+ const agentError = canonicalSuggestions(errorToAgentError(error));
1933
+ const envelope = createAgentErrorEnvelope(options.command || "unknown", agentError, state.runId, errorWarnings(error), options.deprecation ? deprecatedMeta : undefined, deprecationWarnings);
1734
1934
  if (options.mode === "agent-stream") {
1735
1935
  ensureStarted({ bypassQuiet: true });
1736
1936
  if (error instanceof CliInputRequiredError) {
@@ -1796,7 +1996,7 @@ function createCliOutput(options) {
1796
1996
  return output;
1797
1997
  }
1798
1998
  function createAgentEnvelope(options) {
1799
- const safeData = redactDeep(options.data);
1999
+ const safeData = canonicalSuggestionFields(redactDeep(options.data));
1800
2000
  const maxBytes = agentMaxOutputBytes();
1801
2001
  let fullOutput;
1802
2002
  let saveFailed = false;
@@ -1808,13 +2008,16 @@ function createAgentEnvelope(options) {
1808
2008
  return fullOutput.path;
1809
2009
  };
1810
2010
  let text = redactDeep({
1811
- summary: normalizeSummary(options.summary, options.command, options.status, safeData),
1812
- findings: options.findings ?? [],
1813
- evidence_refs: options.evidenceRefs ?? [],
1814
- recommended_actions: options.recommendedActions ?? [],
1815
- next_commands: normalizeNextCommands(options.nextCommands ?? []),
1816
- warnings: options.warnings ?? inferWarnings(safeData)
2011
+ ...canonicalSuggestions({
2012
+ summary: normalizeSummary(options.summary, options.command, options.status, safeData),
2013
+ findings: options.findings ?? [],
2014
+ evidence_refs: options.evidenceRefs ?? [],
2015
+ recommended_actions: options.recommendedActions ?? [],
2016
+ next_commands: normalizeNextCommands(options.nextCommands ?? [])
2017
+ }),
2018
+ warnings: [...canonicalSuggestions(options.warnings ?? inferWarnings(safeData)), ...options.extraWarnings ?? []]
1817
2019
  });
2020
+ const errors = canonicalSuggestions(options.errors ?? []);
1818
2021
  let moved;
1819
2022
  const build = (bounded) => ({
1820
2023
  schema_version: AGENT_SCHEMA_VERSION,
@@ -1826,7 +2029,7 @@ function createAgentEnvelope(options) {
1826
2029
  findings: text.findings,
1827
2030
  evidence_refs: text.evidence_refs,
1828
2031
  recommended_actions: text.recommended_actions,
1829
- next_commands: [...text.next_commands, ...bounded.nextCommands ?? []],
2032
+ next_commands: [...text.next_commands, ...canonicalSuggestions(bounded.nextCommands ?? [])],
1830
2033
  artifacts: [
1831
2034
  ...options.artifacts ?? [],
1832
2035
  ...bounded.fullOutputPath ? [{ kind: "full_output", path: bounded.fullOutputPath, description: "Complete command output (the same JSON --json prints); data in this envelope was bounded." }] : [],
@@ -1834,10 +2037,10 @@ function createAgentEnvelope(options) {
1834
2037
  ],
1835
2038
  warnings: [
1836
2039
  ...text.warnings,
1837
- ...bounded.warning ? [bounded.warning] : [],
2040
+ ...bounded.warning ? [canonicalCommandText(bounded.warning)] : [],
1838
2041
  ...moved ? [movedTextWarning(moved)] : []
1839
2042
  ],
1840
- errors: options.errors ?? [],
2043
+ errors,
1841
2044
  data: bounded.data,
1842
2045
  ...options.meta ? { meta: options.meta } : {},
1843
2046
  ...bounded.truncation || moved ? { truncation: {
@@ -1996,13 +2199,14 @@ function errorWarnings(error) {
1996
2199
  const warnings = error?.warnings;
1997
2200
  return Array.isArray(warnings) && warnings.length ? warnings.filter((w) => typeof w === "string") : undefined;
1998
2201
  }
1999
- function createAgentErrorEnvelope(command, error, runId, warnings) {
2202
+ function createAgentErrorEnvelope(command, error, runId, warnings, meta, extraWarnings) {
2000
2203
  return createAgentEnvelope({
2001
2204
  command,
2002
2205
  status: "error",
2003
2206
  data: null,
2004
2207
  warnings: warnings ?? [],
2005
- meta: runId ? { run_id: runId } : undefined,
2208
+ ...extraWarnings?.length ? { extraWarnings } : {},
2209
+ meta: runId || meta ? { ...meta ?? {}, ...runId ? { run_id: runId } : {} } : undefined,
2006
2210
  summary: {
2007
2211
  text: error.message,
2008
2212
  confidence: "high"
@@ -2423,7 +2627,7 @@ function continuationCommand(invocation, overrides) {
2423
2627
  }
2424
2628
  for (const [key, value] of Object.entries(overrides))
2425
2629
  parts.push(`--${normalize2(key)}=${shellWord(String(value))}`);
2426
- return parts.join(" ");
2630
+ return canonicalCommandText(parts.join(" "));
2427
2631
  }
2428
2632
  var PAGED_LIST_BY_COMMAND = {
2429
2633
  "tool-failure-detail": "examples",
@@ -2432,8 +2636,9 @@ var PAGED_LIST_BY_COMMAND = {
2432
2636
  "problems remainder": "groups"
2433
2637
  };
2434
2638
  function pagedListFor(invocation) {
2435
- const subcommand = invocation.positionals[0];
2436
- return (subcommand !== undefined ? PAGED_LIST_BY_COMMAND[`${invocation.command} ${subcommand}`] : undefined) ?? PAGED_LIST_BY_COMMAND[invocation.command];
2639
+ const { command, positionals } = invocation.routedAs ?? invocation;
2640
+ const subcommand = positionals[0];
2641
+ return (subcommand !== undefined ? PAGED_LIST_BY_COMMAND[`${command} ${subcommand}`] : undefined) ?? PAGED_LIST_BY_COMMAND[command];
2437
2642
  }
2438
2643
  var MAX_PAGE_OFFSET = 1e4;
2439
2644
  function rewritePagination(list, isTopLevel, invocation) {
@@ -2647,4 +2852,4 @@ function apiKeyHeaders(key, options = {}, url) {
2647
2852
  return headers;
2648
2853
  }
2649
2854
 
2650
- export { PROD_BASE_URL, DEFAULT_INGEST_URL, getModaPaths, getModaDir, isLoopbackBaseUrl, describeBaseUrlSource, loadProfileConfig, saveProfileConfig, getActiveProfile, setActiveProfile, upsertProfile, clearStoredApiKeyCredentials, secretFilePathFromRef, resolveSecretReference, resolveApiKeyFromActiveProfile, resolveTenantIdFromActiveProfile, ensureSecretFilePermissions, writeSecretJsonFile, CliInputError, attachInputDetails, CliAccessError, CliInputRequiredError, CliAuthError, CliNotFoundError, CliCancellationError, isNetworkLikeError, isApiLikeError, apiErrorStatus, VERSION, MODA_BASE_URL, loadCliConfig, saveCliConfig, resolveApiKey, embeddedTenantIdFromApiKey, resolveIngestUrl2 as resolveIngestUrl, resolveTenantId, resolveApiTenantId, resolveModaBaseUrl, validateConfig, isPlatformApiKey, setPlatformTenantOverride, apiKeyHeaders, recordApiRequest, getApiRequestCount, resetApiRequestCount, BATCH_MAX_TARGETS, BATCH_CONCURRENCY, parseBatchTarget, collectBatchTargets, mapWithConcurrency, contextTarget, asRecord, asString, asNumber, frustrationAnchorIndex, frustrationsFromEmotions, withFrustrationAnchors, shellWord, trimToolFailureConversations, withToolFailureAnchors, embeddedWindowSize, withoutDetectionWindows, compactProblemDossier, MAX_SCANNED_FILE_BYTES, DEFAULT_MAX_INVENTORY_FILES, DEFAULT_MAX_INVENTORY_TEXT_BYTES, MAX_RECORDED_SKIPS, SKIPPED_DIRS, isSkippedDir, isSkippedPathPrefix, isEvalLikePath, shouldInventoryFile, isTextFile, isSecretishPath, SECRET_KEYS, redactDeep, redactString, packSnapshot, setAgentUpdateNotice, EXIT_OK, EXIT_ERROR, EXIT_DEGRADED, EXIT_AUTH_REQUIRED, EXIT_INPUT_REQUIRED, EXIT_CANCELLED, AGENT_ERROR_CODES, wasOutputCancelled, safeWriteStdout, safeWriteStderr, explicitOutputMode, outputModeFromFlags, resolveOutputMode, createCliOutput, agentEnvelopeFits, errorToAgentError, agentMaxOutputBytes };
2855
+ export { PROD_BASE_URL, DEFAULT_INGEST_URL, getModaPaths, getModaDir, isLoopbackBaseUrl, describeBaseUrlSource, loadProfileConfig, saveProfileConfig, getActiveProfile, setActiveProfile, upsertProfile, clearStoredApiKeyCredentials, secretFilePathFromRef, resolveSecretReference, resolveApiKeyFromActiveProfile, resolveTenantIdFromActiveProfile, ensureSecretFilePermissions, writeSecretJsonFile, CliInputError, attachInputDetails, inputDetailsOf, CliAccessError, CliInputRequiredError, CliAuthError, CliNotFoundError, CliCancellationError, isNetworkLikeError, isApiLikeError, apiErrorStatus, VERSION, MODA_BASE_URL, loadCliConfig, saveCliConfig, resolveApiKey, embeddedTenantIdFromApiKey, resolveIngestUrl2 as resolveIngestUrl, resolveTenantId, resolveApiTenantId, resolveModaBaseUrl, validateConfig, isPlatformApiKey, setPlatformTenantOverride, apiKeyHeaders, recordApiRequest, getApiRequestCount, resetApiRequestCount, BATCH_MAX_TARGETS, BATCH_CONCURRENCY, parseBatchTarget, collectBatchTargets, mapWithConcurrency, contextTarget, asRecord, asString, asNumber, frustrationAnchorIndex, frustrationsFromEmotions, withFrustrationAnchors, shellWord, trimToolFailureConversations, withToolFailureAnchors, embeddedWindowSize, withoutDetectionWindows, compactProblemDossier, MAX_SCANNED_FILE_BYTES, DEFAULT_MAX_INVENTORY_FILES, DEFAULT_MAX_INVENTORY_TEXT_BYTES, MAX_RECORDED_SKIPS, SKIPPED_DIRS, isSkippedDir, isSkippedPathPrefix, isEvalLikePath, shouldInventoryFile, isTextFile, isSecretishPath, SECRET_KEYS, redactDeep, redactString, packSnapshot, LEGACY_NAMES, canonicalCommandText, setAgentUpdateNotice, EXIT_OK, EXIT_ERROR, EXIT_DEGRADED, EXIT_AUTH_REQUIRED, EXIT_INPUT_REQUIRED, EXIT_CANCELLED, AGENT_ERROR_CODES, wasOutputCancelled, safeWriteStdout, safeWriteStderr, explicitOutputMode, outputModeFromFlags, resolveOutputMode, createCliOutput, agentEnvelopeFits, errorToAgentError, agentMaxOutputBytes };