@moda-ai/cli 1.35.0 → 1.36.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/dist/cli.js +218 -2
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +45 -3
package/dist/cli.js
CHANGED
|
@@ -234,6 +234,46 @@ var DetectionReviewSchema = z.object({
|
|
|
234
234
|
verdict: z.enum(DETECTION_VERDICTS),
|
|
235
235
|
note: z.string().max(2000).optional()
|
|
236
236
|
});
|
|
237
|
+
var FALSE_POSITIVE_KINDS = ["problem", "problem-detection", "quote", "tool", "laziness", "hallucination", "custom-signal"];
|
|
238
|
+
var FalsePositiveSchema = z.object({
|
|
239
|
+
kind: z.enum(FALSE_POSITIVE_KINDS),
|
|
240
|
+
target: z.string().min(1).max(255),
|
|
241
|
+
undo: z.boolean(),
|
|
242
|
+
reason: z.string().max(2000).optional(),
|
|
243
|
+
conversation_id: z.string().min(1).max(255).optional(),
|
|
244
|
+
attribution_id: z.string().regex(UUID_RE, "Attribution id must be a UUID").optional(),
|
|
245
|
+
family: z.string().regex(/^[a-z_]{1,64}$/, "Family must be a lowercase emotion family").optional(),
|
|
246
|
+
turn: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()),
|
|
247
|
+
quote: z.string().min(1).max(4000).optional(),
|
|
248
|
+
tool: z.string().min(1).max(255).optional(),
|
|
249
|
+
tool_use_id: z.string().min(1).max(255).optional(),
|
|
250
|
+
msg_index: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()),
|
|
251
|
+
msg_dedup_token: z.string().min(1).max(200).optional()
|
|
252
|
+
}).superRefine((v, ctx) => {
|
|
253
|
+
const need = (ok, message) => {
|
|
254
|
+
if (!ok)
|
|
255
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message });
|
|
256
|
+
};
|
|
257
|
+
if (v.kind === "problem") {
|
|
258
|
+
need(UUID_RE.test(v.target), "Problem id must be a canonical UUID");
|
|
259
|
+
need(!v.undo, "A problem dismissal cannot be undone from the CLI");
|
|
260
|
+
}
|
|
261
|
+
if (v.kind === "problem-detection") {
|
|
262
|
+
need(UUID_RE.test(v.target), "Problem id must be a canonical UUID");
|
|
263
|
+
need(v.conversation_id, "--conversation-id is required for problem-detection");
|
|
264
|
+
need(v.attribution_id, "--attribution-id is required for problem-detection");
|
|
265
|
+
}
|
|
266
|
+
if (v.kind === "quote") {
|
|
267
|
+
need(v.family && v.turn !== undefined && v.quote, "--family, --turn and --quote are required for quote (copy them from moda emotions)");
|
|
268
|
+
}
|
|
269
|
+
if (v.kind === "tool") {
|
|
270
|
+
need(v.tool, "--tool is required for tool (the failing tool name)");
|
|
271
|
+
need(v.tool_use_id || v.msg_index !== undefined, "--tool-use-id or --msg-index is required for tool (from moda tool-failure-detail)");
|
|
272
|
+
}
|
|
273
|
+
if (v.kind === "custom-signal") {
|
|
274
|
+
need(v.conversation_id, "--conversation-id is required for custom-signal");
|
|
275
|
+
}
|
|
276
|
+
});
|
|
237
277
|
var EMOTION_FAMILIES = [
|
|
238
278
|
"frustration",
|
|
239
279
|
"sadness",
|
|
@@ -255,6 +295,13 @@ var HallucinationsSchema = z.object({
|
|
|
255
295
|
conversation_id: z.string().max(200).optional(),
|
|
256
296
|
kind: z.enum(["contradicted", "verified"]).optional()
|
|
257
297
|
});
|
|
298
|
+
var LazinessSchema = z.object({
|
|
299
|
+
days_back: z.number().min(1).max(90).default(7).optional(),
|
|
300
|
+
limit: z.number().min(1).max(50).default(10).optional(),
|
|
301
|
+
offset: z.number().min(0).max(1e4).optional(),
|
|
302
|
+
conversation_id: z.string().max(200).optional(),
|
|
303
|
+
family: z.string().regex(/^[a-z_]{1,64}$/, "Family must be a lowercase laziness family").optional()
|
|
304
|
+
});
|
|
258
305
|
var StepScoresSchema = z.object({
|
|
259
306
|
conversation_id: z.string().min(1)
|
|
260
307
|
});
|
|
@@ -5401,12 +5448,15 @@ Commands:
|
|
|
5401
5448
|
frustrations Get user frustration detections (legacy single-family; see emotions)
|
|
5402
5449
|
emotions Multi-family emotion detections (frustration, sadness, confusion, anxiety, trust, positive)
|
|
5403
5450
|
hallucinations Grounding detections: contradicted/verified outputs with rule breakdown
|
|
5451
|
+
laziness Laziness detections per trace (repeated calls, premature handoffs, ...)
|
|
5404
5452
|
tool-failures Get tool failure overview
|
|
5405
5453
|
tool-failure-detail <tool_name> Get per-tool failure detail
|
|
5406
5454
|
problems Rank cross-signal Problems by root cause (what to fix first)
|
|
5407
5455
|
problem-impact Live problem/use-case impact (--node-id, --problem-id, --mode, --days-back)
|
|
5408
5456
|
problem <problem_id> Open one Problem: dossier, or --evidence/--reports/--traces/--feedback
|
|
5409
5457
|
problem-feedback <problem_id> Mark a Problem fixed, dismiss, rename, or flag a bad attribution
|
|
5458
|
+
false-positive <kind> <target> Mark any detection as a false positive, optional --reason (problem, problem-detection, quote, tool, laziness, hallucination, custom-signal)
|
|
5459
|
+
false-positives [conv_id] Current false-positive marks: all (--kind, --all, --limit) or one trace
|
|
5410
5460
|
detection-reviews <conv_id> Problem detections on a trace with their review state
|
|
5411
5461
|
detection-review <problem_id> Mark a problem detection correct, a false positive, or clear the review
|
|
5412
5462
|
signals List custom signals (name, criteria, status, 7-day stats)
|
|
@@ -5516,6 +5566,11 @@ Emotions flags:
|
|
|
5516
5566
|
--days-back=N --limit=N Window 1-90 (default 7); page size 1-20 (default 10)
|
|
5517
5567
|
--offset=N Skip N detections (0-10000)
|
|
5518
5568
|
|
|
5569
|
+
Laziness flags:
|
|
5570
|
+
--family=F Narrow to one laziness family
|
|
5571
|
+
--conversation-id=ID One trace's detections
|
|
5572
|
+
--days-back=N --limit=N Window 1-90 (default 7); page size 1-50 (default 10)
|
|
5573
|
+
|
|
5519
5574
|
Hallucinations flags:
|
|
5520
5575
|
--kind=contradicted|verified Narrow the detections list
|
|
5521
5576
|
--conversation-id=ID Scope summary + list to one trace ID
|
|
@@ -5529,10 +5584,21 @@ Problem flags (moda problem <id>):
|
|
|
5529
5584
|
|
|
5530
5585
|
Problem-feedback flags:
|
|
5531
5586
|
--action=A mark_fixed|dismiss|flag_attribution|rename (required)
|
|
5532
|
-
--reason=TEXT Required for
|
|
5587
|
+
--reason=TEXT Required for flag_attribution; optional for dismiss
|
|
5533
5588
|
--attribution-id=UUID Required for flag_attribution (ids come from problem --evidence)
|
|
5534
5589
|
--new-name=NAME Required for rename
|
|
5535
5590
|
|
|
5591
|
+
False-positive flags (moda false-positive <kind> <target>):
|
|
5592
|
+
--reason=TEXT Why it is wrong (optional)
|
|
5593
|
+
--undo Remove an earlier mark (every kind except problem)
|
|
5594
|
+
problem <problem_id> Dismiss the problem: hidden at once, logged for review, folded into reconcile
|
|
5595
|
+
problem-detection <problem_id> One detection on a trace; needs --conversation-id and --attribution-id; teaches the problem
|
|
5596
|
+
quote <conversation_id> A user quote; needs --family, --turn and --quote (from moda emotions); audit only
|
|
5597
|
+
tool <conversation_id> One failing tool call; needs --tool and --tool-use-id (or --msg-index); audit only
|
|
5598
|
+
laziness <conversation_id> Laziness on that trace; audit only
|
|
5599
|
+
hallucination <conversation_id> Hallucinations on that trace; audit only
|
|
5600
|
+
custom-signal <signal_id> A hit on that trace (--conversation-id); saved as does_not_fit so the signal learns
|
|
5601
|
+
|
|
5536
5602
|
Detection-review flags (moda detection-review <problem_id>):
|
|
5537
5603
|
--conversation-id=ID Trace the detection is on (required)
|
|
5538
5604
|
--attribution-id=UUID Detection id (from problem --evidence or detection-reviews; required)
|
|
@@ -6404,7 +6470,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6404
6470
|
throw new CliInputError(`Problem id must be a canonical UUID; got "${params.id}".`);
|
|
6405
6471
|
}
|
|
6406
6472
|
const reason = params.reason?.trim() ?? "";
|
|
6407
|
-
if (
|
|
6473
|
+
if (params.action === "flag_attribution" && reason === "") {
|
|
6408
6474
|
throw new CliInputError(`--reason is required for --action=${params.action}.`);
|
|
6409
6475
|
}
|
|
6410
6476
|
if (params.action === "rename" && (params.new_name?.trim() ?? "") === "") {
|
|
@@ -6538,6 +6604,99 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6538
6604
|
context.output.writeData(data);
|
|
6539
6605
|
break;
|
|
6540
6606
|
}
|
|
6607
|
+
case "false-positive": {
|
|
6608
|
+
const usage = `Usage: moda false-positive <${FALSE_POSITIVE_KINDS.join("|")}> <target> --reason=TEXT [--undo]`;
|
|
6609
|
+
const [kind, target] = positionals;
|
|
6610
|
+
if (!kind || !target)
|
|
6611
|
+
throw new CliInputError("<kind> and <target> are required", usage);
|
|
6612
|
+
const params = FalsePositiveSchema.parse({
|
|
6613
|
+
kind,
|
|
6614
|
+
target,
|
|
6615
|
+
undo: flags.undo !== undefined && flags.undo !== "false",
|
|
6616
|
+
...flags.reason !== undefined ? { reason: flags.reason } : {},
|
|
6617
|
+
...flags["conversation-id"] !== undefined ? { conversation_id: flags["conversation-id"] } : {},
|
|
6618
|
+
...flags["attribution-id"] !== undefined ? { attribution_id: flags["attribution-id"] } : {},
|
|
6619
|
+
...flags.family !== undefined ? { family: flags.family } : {},
|
|
6620
|
+
...flags.turn !== undefined ? { turn: flags.turn } : {},
|
|
6621
|
+
...flags.quote !== undefined ? { quote: flags.quote } : {},
|
|
6622
|
+
...flags.tool !== undefined ? { tool: flags.tool } : {},
|
|
6623
|
+
...flags["tool-use-id"] !== undefined ? { tool_use_id: flags["tool-use-id"] } : {},
|
|
6624
|
+
...flags["msg-index"] !== undefined ? { msg_index: flags["msg-index"] } : {},
|
|
6625
|
+
...flags["msg-dedup-token"] !== undefined ? { msg_dedup_token: flags["msg-dedup-token"] } : {}
|
|
6626
|
+
});
|
|
6627
|
+
const reason = params.reason?.trim() ?? "";
|
|
6628
|
+
const post = (path, body, retries) => callDataAPI(path, { method: "POST", body: JSON.stringify(body), headers: { "Content-Type": "application/json" } }, retries === undefined ? undefined : { retries });
|
|
6629
|
+
let data;
|
|
6630
|
+
switch (params.kind) {
|
|
6631
|
+
case "problem":
|
|
6632
|
+
data = await post(`/problems/${params.target}/feedback`, { action: "dismiss", reason, actor: "moda-cli" }, 0);
|
|
6633
|
+
break;
|
|
6634
|
+
case "problem-detection":
|
|
6635
|
+
data = await post(`/problems/${params.target}/detection-reviews`, {
|
|
6636
|
+
conversation_id: params.conversation_id,
|
|
6637
|
+
attribution_id: params.attribution_id,
|
|
6638
|
+
verdict: params.undo ? "clear" : "false_positive",
|
|
6639
|
+
...params.undo ? {} : { note: reason },
|
|
6640
|
+
request_nonce: randomUUID2()
|
|
6641
|
+
});
|
|
6642
|
+
break;
|
|
6643
|
+
case "custom-signal":
|
|
6644
|
+
if (params.undo) {
|
|
6645
|
+
data = await callDataAPI(`/custom-signals/${encodeURIComponent(params.target)}/labels/${encodeURIComponent(params.conversation_id ?? "")}`, { method: "DELETE" }, { retries: 0 });
|
|
6646
|
+
break;
|
|
6647
|
+
}
|
|
6648
|
+
data = await post(`/custom-signals/${encodeURIComponent(params.target)}/labels`, {
|
|
6649
|
+
conversation_id: params.conversation_id,
|
|
6650
|
+
label: "does_not_fit",
|
|
6651
|
+
note: reason,
|
|
6652
|
+
...params.msg_index !== undefined ? { msg_index: params.msg_index } : {},
|
|
6653
|
+
...params.msg_dedup_token ? { msg_dedup_token: params.msg_dedup_token } : {}
|
|
6654
|
+
}, 0);
|
|
6655
|
+
break;
|
|
6656
|
+
default: {
|
|
6657
|
+
const apiKind = { quote: "frustration_quote", tool: "tool_call", laziness: "laziness", hallucination: "hallucination" }[params.kind];
|
|
6658
|
+
data = await post("/false-positives", {
|
|
6659
|
+
kind: apiKind,
|
|
6660
|
+
verdict: params.undo ? "clear" : "false_positive",
|
|
6661
|
+
...params.undo ? {} : { note: reason },
|
|
6662
|
+
conversation_id: params.target,
|
|
6663
|
+
...params.kind === "tool" ? {
|
|
6664
|
+
tool_name: params.tool,
|
|
6665
|
+
...params.tool_use_id ? { tool_use_id: params.tool_use_id } : { msg_index: params.msg_index }
|
|
6666
|
+
} : {},
|
|
6667
|
+
...params.kind === "quote" ? { family: params.family, turn: params.turn, quote: params.quote } : {},
|
|
6668
|
+
request_nonce: randomUUID2()
|
|
6669
|
+
});
|
|
6670
|
+
}
|
|
6671
|
+
}
|
|
6672
|
+
context.output.writeData(data);
|
|
6673
|
+
break;
|
|
6674
|
+
}
|
|
6675
|
+
case "false-positives": {
|
|
6676
|
+
if (!positional) {
|
|
6677
|
+
const kinds = { quote: "frustration_quote", tool: "tool_call", laziness: "laziness", hallucination: "hallucination", "custom-signal": "custom_signal" };
|
|
6678
|
+
const query = new URLSearchParams;
|
|
6679
|
+
if (flags.kind !== undefined) {
|
|
6680
|
+
if (!kinds[flags.kind])
|
|
6681
|
+
throw new CliInputError(`--kind must be one of ${Object.keys(kinds).join("|")}`);
|
|
6682
|
+
query.set("kind", kinds[flags.kind]);
|
|
6683
|
+
}
|
|
6684
|
+
if (flags.limit !== undefined) {
|
|
6685
|
+
if (!/^\d+$/.test(flags.limit) || Number(flags.limit) < 1 || Number(flags.limit) > 200)
|
|
6686
|
+
throw new CliInputError("--limit must be 1-200");
|
|
6687
|
+
query.set("limit", flags.limit);
|
|
6688
|
+
}
|
|
6689
|
+
if (flags.all !== undefined && flags.all !== "false")
|
|
6690
|
+
query.set("include_cleared", "true");
|
|
6691
|
+
const queryString = query.toString() ? `?${query.toString()}` : "";
|
|
6692
|
+
const data2 = await callDataAPI(`/false-positives${queryString}`);
|
|
6693
|
+
context.output.writeData(data2);
|
|
6694
|
+
break;
|
|
6695
|
+
}
|
|
6696
|
+
const data = await callDataAPI(`/conversations/${encodeURIComponent(positional)}/false-positives`);
|
|
6697
|
+
context.output.writeData(data);
|
|
6698
|
+
break;
|
|
6699
|
+
}
|
|
6541
6700
|
case "emotions": {
|
|
6542
6701
|
const args = flagsToArgs(flags);
|
|
6543
6702
|
const params = EmotionsSchema.parse(args);
|
|
@@ -6555,6 +6714,28 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6555
6714
|
context.output.writeData(data);
|
|
6556
6715
|
break;
|
|
6557
6716
|
}
|
|
6717
|
+
case "laziness": {
|
|
6718
|
+
const args = flagsToArgs(flags);
|
|
6719
|
+
if (flags["conversation-id"] !== undefined) {
|
|
6720
|
+
args.conversation_id = flags["conversation-id"];
|
|
6721
|
+
}
|
|
6722
|
+
const params = LazinessSchema.parse(args);
|
|
6723
|
+
const query = new URLSearchParams;
|
|
6724
|
+
if (params.days_back)
|
|
6725
|
+
query.set("days_back", params.days_back.toString());
|
|
6726
|
+
if (params.limit)
|
|
6727
|
+
query.set("limit", params.limit.toString());
|
|
6728
|
+
if (params.offset !== undefined)
|
|
6729
|
+
query.set("offset", params.offset.toString());
|
|
6730
|
+
if (params.conversation_id)
|
|
6731
|
+
query.set("conversation_id", params.conversation_id);
|
|
6732
|
+
if (params.family)
|
|
6733
|
+
query.set("family", params.family);
|
|
6734
|
+
const queryString = query.toString() ? `?${query.toString()}` : "";
|
|
6735
|
+
const data = await callDataAPI(`/laziness${queryString}`);
|
|
6736
|
+
context.output.writeData(data);
|
|
6737
|
+
break;
|
|
6738
|
+
}
|
|
6558
6739
|
case "hallucinations": {
|
|
6559
6740
|
const args = flagsToArgs(flags);
|
|
6560
6741
|
if (flags["conversation-id"] !== undefined) {
|
|
@@ -7181,6 +7362,32 @@ var commandRegistry = createCommandRegistry([
|
|
|
7181
7362
|
...dataApiDefaults,
|
|
7182
7363
|
mutability: "write"
|
|
7183
7364
|
}),
|
|
7365
|
+
legacyCommand({
|
|
7366
|
+
name: "false-positive",
|
|
7367
|
+
description: "Flag a detection as a false positive with a reason: problem, problem-detection, quote, tool, laziness, hallucination, or custom-signal",
|
|
7368
|
+
examples: [
|
|
7369
|
+
'moda false-positive problem <problem_id> --reason="two unrelated tools"',
|
|
7370
|
+
'moda false-positive problem-detection <problem_id> --conversation-id=<id> --attribution-id=<uuid> --reason="refund was approved"',
|
|
7371
|
+
'moda false-positive quote <conversation_id> --family=frustration --turn=3 --quote="this is useless lol" --reason="joking"',
|
|
7372
|
+
'moda false-positive tool <conversation_id> --tool=send_invoice --tool-use-id=<id> --reason="retried upstream"',
|
|
7373
|
+
'moda false-positive laziness <conversation_id> --reason="reload after context reset is expected"',
|
|
7374
|
+
"moda false-positive hallucination <conversation_id> --undo",
|
|
7375
|
+
"moda false-positive custom-signal <signal_id> --conversation-id=<id> --undo",
|
|
7376
|
+
'moda false-positive custom-signal <signal_id> --conversation-id=<id> --reason="refund was approved"'
|
|
7377
|
+
],
|
|
7378
|
+
...dataApiDefaults,
|
|
7379
|
+
mutability: "write"
|
|
7380
|
+
}),
|
|
7381
|
+
legacyCommand({
|
|
7382
|
+
name: "false-positives",
|
|
7383
|
+
description: "List current false-positive marks across the workspace, or on one trace (with problem detection reviews)",
|
|
7384
|
+
examples: [
|
|
7385
|
+
"moda false-positives",
|
|
7386
|
+
"moda false-positives --kind=tool --all",
|
|
7387
|
+
"moda false-positives <conversation_id>"
|
|
7388
|
+
],
|
|
7389
|
+
...dataApiDefaults
|
|
7390
|
+
}),
|
|
7184
7391
|
legacyCommand({
|
|
7185
7392
|
name: "signals",
|
|
7186
7393
|
description: "List custom signals with criteria, status, and 7-day judged/matched stats",
|
|
@@ -7221,6 +7428,15 @@ var commandRegistry = createCommandRegistry([
|
|
|
7221
7428
|
],
|
|
7222
7429
|
...dataApiDefaults
|
|
7223
7430
|
}),
|
|
7431
|
+
legacyCommand({
|
|
7432
|
+
name: "laziness",
|
|
7433
|
+
description: "Laziness detections per trace: repeated tool calls, premature handoffs, and other lazy patterns",
|
|
7434
|
+
examples: [
|
|
7435
|
+
"moda laziness --days-back=30",
|
|
7436
|
+
"moda laziness --conversation-id=<id>"
|
|
7437
|
+
],
|
|
7438
|
+
...dataApiDefaults
|
|
7439
|
+
}),
|
|
7224
7440
|
legacyCommand({
|
|
7225
7441
|
name: "hallucinations",
|
|
7226
7442
|
description: "Grounding detections: contradicted/verified outputs with rule breakdown",
|
package/package.json
CHANGED
package/skills/moda-cli/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: moda-cli
|
|
3
|
-
version: 2.
|
|
3
|
+
version: 2.7.0
|
|
4
4
|
description: Query Moda's AI agent trace analytics and manage code-first prompt versions from the terminal — semantic/keyword/hybrid message search, overview KPIs, topic clusters, message context, user frustration detections, tool failures, custom signals, false-positive review of detections, and moda prompts status/sync/promote. Use when the user asks about moda, modaflows, trace or conversation analytics, prompt management, user frustrations, agent observability, tool failure debugging, custom signals, marking a detection as a false positive, wants to find traces or tool calls about a topic, or wants to investigate how their AI agent is performing.
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -750,6 +750,45 @@ Rules that keep the proof honest:
|
|
|
750
750
|
|
|
751
751
|
### 9. Custom signals and false positives
|
|
752
752
|
|
|
753
|
+
**Mark anything as a false positive with one command.** `--reason` (why the
|
|
754
|
+
detection is wrong) is optional but recommended; marks are logged for Moda's review.
|
|
755
|
+
A marked item disappears from every list and count (`moda problems`,
|
|
756
|
+
`hallucinations`, `laziness`, `tool-failures`, problem evidence, the dashboard);
|
|
757
|
+
`--undo` brings it back.
|
|
758
|
+
|
|
759
|
+
```bash
|
|
760
|
+
moda false-positive problem <problem_id> --reason="two unrelated tools" # dismiss: hidden at once
|
|
761
|
+
moda false-positive problem-detection <problem_id> --conversation-id=<id> \
|
|
762
|
+
--attribution-id=<uuid> --reason="refund was approved" # one piece of evidence
|
|
763
|
+
moda false-positive quote <conversation_id> --family=frustration --turn=3 \
|
|
764
|
+
--quote="this is useless lol" --reason="user was joking" # one user quote
|
|
765
|
+
moda false-positive tool <conversation_id> --tool=send_invoice \
|
|
766
|
+
--tool-use-id=<tool_use_id> --reason="retried upstream" # one failing tool call
|
|
767
|
+
moda false-positive laziness <conversation_id> --reason="reload is expected"
|
|
768
|
+
moda false-positive hallucination <conversation_id> --reason="price came from the tool result"
|
|
769
|
+
moda false-positive custom-signal <signal_id> --conversation-id=<id> --reason="refund was approved"
|
|
770
|
+
moda false-positive laziness <conversation_id> --undo # remove a mark (any kind but problem)
|
|
771
|
+
moda false-positives # every current mark (--kind=tool, --all, --limit)
|
|
772
|
+
moda false-positives <conversation_id> # marks + problem reviews on a trace
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
What each flag does downstream:
|
|
776
|
+
|
|
777
|
+
| Kind | Effect |
|
|
778
|
+
|---|---|
|
|
779
|
+
| `problem` | Dismisses the problem: it leaves `moda problems` and the dashboard at once, and the reason is folded into the next reconcile. Cannot be undone from the CLI |
|
|
780
|
+
| `problem-detection` | Drops that evidence from the problem and teaches the problem reader (same as `detection-review --verdict=false_positive`) |
|
|
781
|
+
| `custom-signal` | Saved as a `does_not_fit` label with the reason, so the signal learns from it and the live match is retracted (same as `signal-label`). `--undo` removes the label |
|
|
782
|
+
| `quote`, `tool`, `laziness`, `hallucination` | Audit only: recorded for review, never fed back to the detectors |
|
|
783
|
+
|
|
784
|
+
Find targets with the read commands: `--family`, `--turn` and `--quote` verbatim
|
|
785
|
+
from a `user_quotes` entry in `moda emotions`; a failing call's `tool_use_id` (or `msg_index` when it has none) from
|
|
786
|
+
`moda tool-failure-detail <tool_name>`;
|
|
787
|
+
laziness traces from `moda laziness`; hallucination traces from
|
|
788
|
+
`moda hallucinations`; custom-signal hits from `moda trace-signals` or
|
|
789
|
+
`moda signal <id> --detections`; problem evidence ids from
|
|
790
|
+
`moda problem <id> --evidence`.
|
|
791
|
+
|
|
753
792
|
**Custom signals** are tenant-defined behaviors (pass/fail criteria) judged on
|
|
754
793
|
every trace. Read them, then label hits so the signal learns:
|
|
755
794
|
|
|
@@ -768,7 +807,7 @@ match; `--label=fits` confirms it. Pass the hit's `anchor_msg_index` (or
|
|
|
768
807
|
message, and always give a `--note` when rejecting. Labels are throttled to 10
|
|
769
808
|
per minute per API key and are never retried automatically.
|
|
770
809
|
|
|
771
|
-
**Problem detections** (the dashboard's
|
|
810
|
+
**Problem detections** (the dashboard's flag on problem evidence) are reviewed with
|
|
772
811
|
`detection-review`. A `false_positive` drops the detection out of
|
|
773
812
|
`moda problem <id> --evidence` and is fed back to the problem reader; `clear`
|
|
774
813
|
undoes an earlier review.
|
|
@@ -954,7 +993,10 @@ npx: `npx -p @moda-ai/cli moda <command>`.
|
|
|
954
993
|
| `moda tool-failure-detail <tool_name>` | Per-tool failure breakdown + examples |
|
|
955
994
|
| `moda problems` | Rank cross-signal Problems by root cause (what to fix first) |
|
|
956
995
|
| `moda problem <problem_id>` | One Problem: dossier, or `--evidence`/`--reports`/`--traces`/`--feedback` pages (`--conversations` is a legacy alias of `--traces`) (`--limit` 1–50, `--cursor` verbatim keyset token) |
|
|
957
|
-
| `moda problem-feedback <problem_id>` | Write: `--action=mark_fixed\|dismiss\|flag_attribution\|rename`. `--reason` required for dismiss
|
|
996
|
+
| `moda problem-feedback <problem_id>` | Write: `--action=mark_fixed\|dismiss\|flag_attribution\|rename`. `--reason` required for flag_attribution, optional for dismiss; `--new-name` for rename; `--attribution-id` (UUID) required for flag_attribution |
|
|
997
|
+
| `moda false-positive <kind> <target>` | Write: kinds `problem\|problem-detection\|quote\|tool\|laziness\|hallucination\|custom-signal`; `--reason` optional; problem-detection needs `--conversation-id` + `--attribution-id`; quote needs `--family`, `--turn`, `--quote`; tool needs `--tool` plus `--tool-use-id` or `--msg-index`; custom-signal needs `--conversation-id`; `--undo` removes a mark (not for problem) |
|
|
998
|
+
| `moda false-positives [conversation_id]` | Current false-positive marks: all (`--kind`, `--all` to include removed, `--limit`) or one trace with its problem detection reviews |
|
|
999
|
+
| `moda laziness` | Laziness detections per trace (`--days-back`, `--limit` 1-50, `--conversation-id`, `--family`) |
|
|
958
1000
|
| `moda detection-reviews <conversation_id>` | Problem detections on a trace with review state (`--attribution-id=UUID` narrows to one) |
|
|
959
1001
|
| `moda detection-review <problem_id>` | Write: `--conversation-id`, `--attribution-id` (UUID), `--verdict=correct\|false_positive\|clear`, optional `--note` |
|
|
960
1002
|
| `moda signals` | Custom signals: criteria, status, 7-day judged/matched stats |
|