@moda-ai/cli 1.13.10 → 1.13.11
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/README.md +0 -4
- package/dist/agent-schemas.js +1 -2
- package/dist/cli.js +1 -39
- package/dist/production-intelligence.d.ts +2 -4
- package/dist/production-intelligence.js +2 -75
- package/dist/schemas.d.ts +0 -16
- package/dist/schemas.js +0 -8
- package/dist/tui.js +0 -1
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +3 -19
package/README.md
CHANGED
|
@@ -58,9 +58,6 @@ moda tool-failures # Tool failure overview
|
|
|
58
58
|
moda tool-failure-detail <tool_name> # Per-tool failure detail
|
|
59
59
|
moda tool-failure-detail <tool_name> --include-window --window=1
|
|
60
60
|
|
|
61
|
-
moda loops # Currently-active loop detections
|
|
62
|
-
moda loop <detection_id> # One loop detail (signature + blast radius)
|
|
63
|
-
|
|
64
61
|
# Prompt management
|
|
65
62
|
moda prompts init # Create .moda/prompts.yml
|
|
66
63
|
moda prompts status # Read-only local prompt status
|
|
@@ -75,7 +72,6 @@ All commands output JSON. Pipe to `jq` for filtering:
|
|
|
75
72
|
```bash
|
|
76
73
|
moda overview | jq '.frustrations'
|
|
77
74
|
moda frustrations | jq '.frustrations[].primary_cause'
|
|
78
|
-
moda loops | jq '.loops | sort_by(-.cycle_visits) | .[0:5] | .[].loop_signature_human'
|
|
79
75
|
```
|
|
80
76
|
|
|
81
77
|
## Prompt Management
|
package/dist/agent-schemas.js
CHANGED
|
@@ -224,7 +224,7 @@ const productionEvidenceRefSchema = {
|
|
|
224
224
|
id: { type: 'string' },
|
|
225
225
|
kind: {
|
|
226
226
|
type: 'string',
|
|
227
|
-
enum: ['data_api', 'tool_failure', 'frustration', '
|
|
227
|
+
enum: ['data_api', 'tool_failure', 'frustration', 'run', 'harness', 'ask'],
|
|
228
228
|
},
|
|
229
229
|
label: { type: 'string' },
|
|
230
230
|
endpoint: { type: 'string' },
|
|
@@ -284,7 +284,6 @@ const productionFindingSchema = {
|
|
|
284
284
|
type: 'string',
|
|
285
285
|
enum: [
|
|
286
286
|
'tool_failure',
|
|
287
|
-
'loop',
|
|
288
287
|
'frustration',
|
|
289
288
|
'partial_run',
|
|
290
289
|
'prompt_regression',
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { validateConfig, VERSION, resolveApiKey } from './config.js';
|
|
4
4
|
import { callDataAPI, ApiError, getApiRequestCount, resetApiRequestCount, } from './api-client.js';
|
|
5
|
-
import { OverviewSchema, ClustersSchema, ClusterConversationsSchema, ConversationsSchema, SearchSchema, WorldStateSchema, ContextSchema, AuditSchema, FrustrationsSchema, ToolFailuresSchema, ToolFailureDetailSchema,
|
|
5
|
+
import { OverviewSchema, ClustersSchema, ClusterConversationsSchema, ConversationsSchema, SearchSchema, WorldStateSchema, ContextSchema, AuditSchema, FrustrationsSchema, ToolFailuresSchema, ToolFailureDetailSchema, } from './schemas.js';
|
|
6
6
|
import { withFrustrationAnchors, withToolFailureAnchors, embeddedWindowSize, asRecord, asString, asNumber } from './transforms.js';
|
|
7
7
|
import { runPromptsCommand } from './prompts.js';
|
|
8
8
|
// Coding-agent capture (shadow workspace / Shadow Spark / trace hooks) is temporarily
|
|
@@ -171,9 +171,6 @@ Commands:
|
|
|
171
171
|
tool-failures Get tool failure overview
|
|
172
172
|
tool-failure-detail <tool_name> Get per-tool failure detail
|
|
173
173
|
|
|
174
|
-
loops Currently-active loop detections
|
|
175
|
-
loop <detection_id> Single loop detail
|
|
176
|
-
|
|
177
174
|
Prompt management:
|
|
178
175
|
prompts init Create .moda/prompts.yml
|
|
179
176
|
prompts status Show local prompt changes
|
|
@@ -306,8 +303,6 @@ Examples:
|
|
|
306
303
|
moda context <conversation_id> --window=3
|
|
307
304
|
moda audit <conversation_id|trace_id>
|
|
308
305
|
moda audit <trace_id> --kind=trace --json
|
|
309
|
-
moda loops --limit=10
|
|
310
|
-
moda loop 12345678-1234-1234-1234-1234567890ab
|
|
311
306
|
moda prompts status
|
|
312
307
|
moda prompts sync
|
|
313
308
|
moda prompts promote support.triage --label=prod --version=pver_abc123
|
|
@@ -617,27 +612,6 @@ export async function runCommand(command, positional, flags, positionals = posit
|
|
|
617
612
|
await printWithOptionalWindows(withToolFailureAnchors(data), 'examples', params.include_window === true, params.window ?? 1, context.output);
|
|
618
613
|
break;
|
|
619
614
|
}
|
|
620
|
-
case 'loops': {
|
|
621
|
-
const args = flagsToArgs(flags);
|
|
622
|
-
const params = LoopsSchema.parse(args);
|
|
623
|
-
const query = new URLSearchParams();
|
|
624
|
-
if (params.limit)
|
|
625
|
-
query.set('limit', params.limit.toString());
|
|
626
|
-
const queryString = query.toString() ? `?${query.toString()}` : '';
|
|
627
|
-
const data = await callDataAPI(`/loops/active${queryString}`);
|
|
628
|
-
context.output.writeData(data);
|
|
629
|
-
break;
|
|
630
|
-
}
|
|
631
|
-
case 'loop': {
|
|
632
|
-
if (!positional) {
|
|
633
|
-
throw new CliInputError('<detection_id> is required', 'Usage: moda loop <detection_id>');
|
|
634
|
-
}
|
|
635
|
-
const args = flagsToArgs(flags, 'detection_id', positional);
|
|
636
|
-
const params = LoopDetailSchema.parse(args);
|
|
637
|
-
const data = await callDataAPI(`/loops/${params.detection_id}`);
|
|
638
|
-
context.output.writeData(data);
|
|
639
|
-
break;
|
|
640
|
-
}
|
|
641
615
|
default:
|
|
642
616
|
throw new CliInputError(`Unknown command '${command}'`, 'Run "moda --help" for usage information.');
|
|
643
617
|
}
|
|
@@ -1044,18 +1018,6 @@ export const commandRegistry = createCommandRegistry([
|
|
|
1044
1018
|
examples: ['moda tool-failure-detail search --include-window'],
|
|
1045
1019
|
...dataApiDefaults,
|
|
1046
1020
|
}),
|
|
1047
|
-
legacyCommand({
|
|
1048
|
-
name: 'loops',
|
|
1049
|
-
description: 'List currently-active loop detections',
|
|
1050
|
-
examples: ['moda loops --limit=10'],
|
|
1051
|
-
...dataApiDefaults,
|
|
1052
|
-
}),
|
|
1053
|
-
legacyCommand({
|
|
1054
|
-
name: 'loop',
|
|
1055
|
-
description: 'Get a single loop detection',
|
|
1056
|
-
examples: ['moda loop 12345678-1234-1234-1234-1234567890ab'],
|
|
1057
|
-
...dataApiDefaults,
|
|
1058
|
-
}),
|
|
1059
1021
|
legacyCommand({
|
|
1060
1022
|
name: 'prompts',
|
|
1061
1023
|
description: 'Manage prompt versions and labels',
|
|
@@ -5,10 +5,10 @@ declare const INVESTIGATION_SCHEMA_VERSION = "production_investigation.v0.1";
|
|
|
5
5
|
declare const OVERVIEW_SCHEMA_VERSION = "production_overview.v0.1";
|
|
6
6
|
declare const ASK_SCHEMA_VERSION = "production_ask.v0.1";
|
|
7
7
|
type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
8
|
-
type FindingKind = 'tool_failure' | '
|
|
8
|
+
type FindingKind = 'tool_failure' | 'frustration' | 'prompt_regression' | 'skill_gap' | 'insufficient_data';
|
|
9
9
|
export interface ProductionEvidenceRef {
|
|
10
10
|
id: string;
|
|
11
|
-
kind: 'data_api' | 'tool_failure' | 'frustration' | '
|
|
11
|
+
kind: 'data_api' | 'tool_failure' | 'frustration' | 'harness' | 'ask';
|
|
12
12
|
label: string;
|
|
13
13
|
endpoint?: string;
|
|
14
14
|
conversationId?: string;
|
|
@@ -54,7 +54,6 @@ export interface ProductionInvestigation {
|
|
|
54
54
|
scope: {
|
|
55
55
|
conversationId?: string;
|
|
56
56
|
toolName?: string;
|
|
57
|
-
loopId?: string;
|
|
58
57
|
question?: string;
|
|
59
58
|
};
|
|
60
59
|
summary: {
|
|
@@ -137,7 +136,6 @@ export declare function investigateProduction(options: {
|
|
|
137
136
|
cwd: string;
|
|
138
137
|
conversationId?: string;
|
|
139
138
|
toolName?: string;
|
|
140
|
-
loopId?: string;
|
|
141
139
|
question?: string;
|
|
142
140
|
failureOnly?: boolean;
|
|
143
141
|
}): Promise<ProductionInvestigation>;
|
|
@@ -66,7 +66,6 @@ export async function runProductionCommand(context) {
|
|
|
66
66
|
cwd: context.cwd,
|
|
67
67
|
conversationId: context.flags.conversation,
|
|
68
68
|
toolName: context.flags.tool,
|
|
69
|
-
loopId: context.flags.loop,
|
|
70
69
|
});
|
|
71
70
|
writeInvestigation(context, investigation);
|
|
72
71
|
return { exitCode: 0 };
|
|
@@ -127,16 +126,12 @@ export async function investigateProduction(options) {
|
|
|
127
126
|
? `/tool-failures/${encodeURIComponent(options.toolName)}?days_back=${options.daysBack}&limit=5`
|
|
128
127
|
: `/tool-failures?days_back=${options.daysBack}`;
|
|
129
128
|
const frustrationsEndpoint = `/frustrations?days_back=${options.daysBack}&limit=5`;
|
|
130
|
-
const
|
|
131
|
-
? `/loops/${encodeURIComponent(options.loopId)}`
|
|
132
|
-
: '/loops/active?limit=20';
|
|
133
|
-
const [overview, tools, frustrations, loops] = await Promise.all([
|
|
129
|
+
const [overview, tools, frustrations] = await Promise.all([
|
|
134
130
|
safeData(overviewEndpoint),
|
|
135
131
|
safeData(toolEndpoint),
|
|
136
132
|
safeData(frustrationsEndpoint),
|
|
137
|
-
safeData(loopsEndpoint),
|
|
138
133
|
]);
|
|
139
|
-
for (const [key, result] of Object.entries({ overview, tools, frustrations
|
|
134
|
+
for (const [key, result] of Object.entries({ overview, tools, frustrations })) {
|
|
140
135
|
sourceStatus[key] = result.status;
|
|
141
136
|
if (result.warning)
|
|
142
137
|
warnings.push(result.warning);
|
|
@@ -147,10 +142,6 @@ export async function investigateProduction(options) {
|
|
|
147
142
|
findings.push(...toolFailureFindings(tools.data, options.daysBack, hints, evidenceRefs, options.toolName));
|
|
148
143
|
if (!options.failureOnly) {
|
|
149
144
|
findings.push(...frustrationFindings(frustrations.data, options.daysBack, evidenceRefs));
|
|
150
|
-
findings.push(...loopFindings(loops.data, evidenceRefs, options.loopId));
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
findings.push(...loopFindings(loops.data, evidenceRefs, options.loopId));
|
|
154
145
|
}
|
|
155
146
|
if (findings.length === 0) {
|
|
156
147
|
findings.push(insufficientDataFinding(overview.data, evidenceRefs));
|
|
@@ -165,7 +156,6 @@ export async function investigateProduction(options) {
|
|
|
165
156
|
scope: {
|
|
166
157
|
...(options.conversationId ? { conversationId: options.conversationId } : {}),
|
|
167
158
|
...(options.toolName ? { toolName: options.toolName } : {}),
|
|
168
|
-
...(options.loopId ? { loopId: options.loopId } : {}),
|
|
169
159
|
...(options.question ? { question: options.question } : {}),
|
|
170
160
|
},
|
|
171
161
|
summary: summarizeInvestigation(boundedFindings),
|
|
@@ -444,44 +434,6 @@ function frustrationFindings(data, daysBack, evidenceRefs) {
|
|
|
444
434
|
}],
|
|
445
435
|
}];
|
|
446
436
|
}
|
|
447
|
-
function loopFindings(data, evidenceRefs, scopedLoopId) {
|
|
448
|
-
const rows = loopRows(data);
|
|
449
|
-
return rows.flatMap((loop) => {
|
|
450
|
-
const id = loop.id || scopedLoopId;
|
|
451
|
-
if (!id)
|
|
452
|
-
return [];
|
|
453
|
-
const evidenceId = `loop:${id}`;
|
|
454
|
-
evidenceRefs.push({
|
|
455
|
-
id: evidenceId,
|
|
456
|
-
kind: 'loop',
|
|
457
|
-
label: loop.signature || `${loop.type || 'Loop'} detected`,
|
|
458
|
-
endpoint: `/loops/${id}`,
|
|
459
|
-
detectionId: id,
|
|
460
|
-
conversationId: loop.conversationId,
|
|
461
|
-
value: loop.raw,
|
|
462
|
-
});
|
|
463
|
-
return [{
|
|
464
|
-
id: `finding_loop_${slug(id)}`,
|
|
465
|
-
kind: 'loop',
|
|
466
|
-
title: loop.signature || `${loop.type || 'Loop'} detected`,
|
|
467
|
-
severity: loop.blastRadius >= 5 ? 'high' : 'medium',
|
|
468
|
-
confidence: 'high',
|
|
469
|
-
impactScore: 84 + Math.min(loop.blastRadius, 10),
|
|
470
|
-
rankReason: `Active loop detection${loop.blastRadius ? ` with blast radius ${loop.blastRadius}` : ''}.`,
|
|
471
|
-
summary: loop.rootCause || 'The agent appears to repeat work or retry a failing path.',
|
|
472
|
-
evidenceRefIds: [evidenceId],
|
|
473
|
-
likelyLocations: [unknownLocation('prompt', 'Loops often come from retry policy, stop conditions, or tool handling.')],
|
|
474
|
-
recommendedActions: [{
|
|
475
|
-
id: `action_loop_${slug(id)}`,
|
|
476
|
-
title: 'Inspect loop detail.',
|
|
477
|
-
rationale: 'Loop detail includes signature, cycle length, and root-cause hypothesis.',
|
|
478
|
-
command: `moda loop ${id}`,
|
|
479
|
-
mutability: 'read',
|
|
480
|
-
requiresApproval: false,
|
|
481
|
-
}],
|
|
482
|
-
}];
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
437
|
function insufficientDataFinding(overview, evidenceRefs) {
|
|
486
438
|
const evidenceId = 'overview:data';
|
|
487
439
|
if (!evidenceRefs.some((ref) => ref.id === evidenceId)) {
|
|
@@ -1060,28 +1012,6 @@ function toolRows(data, scopedTool) {
|
|
|
1060
1012
|
}];
|
|
1061
1013
|
});
|
|
1062
1014
|
}
|
|
1063
|
-
function loopRows(data) {
|
|
1064
|
-
const record = asRecord(data);
|
|
1065
|
-
const rows = Array.isArray(record?.loops)
|
|
1066
|
-
? record.loops
|
|
1067
|
-
: asRecord(record)
|
|
1068
|
-
? [record]
|
|
1069
|
-
: [];
|
|
1070
|
-
return rows.flatMap((item) => {
|
|
1071
|
-
const row = asRecord(item);
|
|
1072
|
-
if (!row)
|
|
1073
|
-
return [];
|
|
1074
|
-
return [{
|
|
1075
|
-
id: asString(row.detection_id) ?? '',
|
|
1076
|
-
type: asString(row.loop_type) ?? undefined,
|
|
1077
|
-
signature: asString(row.loop_signature_human) ?? undefined,
|
|
1078
|
-
blastRadius: numberValue(row.blast_radius),
|
|
1079
|
-
conversationId: asString(row.conversation_id) ?? undefined,
|
|
1080
|
-
rootCause: asString(row.root_cause_hypothesis) ?? undefined,
|
|
1081
|
-
raw: row,
|
|
1082
|
-
}];
|
|
1083
|
-
}).filter((loop) => loop.id);
|
|
1084
|
-
}
|
|
1085
1015
|
function firstQuote(row) {
|
|
1086
1016
|
const quotes = Array.isArray(row?.user_quotes) ? row.user_quotes : [];
|
|
1087
1017
|
const first = asRecord(quotes[0]);
|
|
@@ -1335,7 +1265,6 @@ function evidenceKind(value) {
|
|
|
1335
1265
|
if (value === 'data_api' ||
|
|
1336
1266
|
value === 'tool_failure' ||
|
|
1337
1267
|
value === 'frustration' ||
|
|
1338
|
-
value === 'loop' ||
|
|
1339
1268
|
value === 'harness' ||
|
|
1340
1269
|
value === 'ask')
|
|
1341
1270
|
return value;
|
|
@@ -1355,8 +1284,6 @@ function purposeForCommand(command) {
|
|
|
1355
1284
|
return 'Inspect tool failure examples and conversation anchors.';
|
|
1356
1285
|
if (command.startsWith('moda context'))
|
|
1357
1286
|
return 'Read the relevant conversation window.';
|
|
1358
|
-
if (command.startsWith('moda loop'))
|
|
1359
|
-
return 'Inspect loop detection details.';
|
|
1360
1287
|
if (command.startsWith('moda doctor'))
|
|
1361
1288
|
return 'Validate Moda setup and data flow.';
|
|
1362
1289
|
if (command.startsWith('moda overview'))
|
package/dist/schemas.d.ts
CHANGED
|
@@ -185,20 +185,4 @@ export declare const SearchSchema: z.ZodObject<{
|
|
|
185
185
|
limit?: number | undefined;
|
|
186
186
|
user_id?: string | undefined;
|
|
187
187
|
}>;
|
|
188
|
-
/** moda loops — currently active loop detections. */
|
|
189
|
-
export declare const LoopsSchema: z.ZodObject<{
|
|
190
|
-
limit: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
191
|
-
}, "strip", z.ZodTypeAny, {
|
|
192
|
-
limit?: number | undefined;
|
|
193
|
-
}, {
|
|
194
|
-
limit?: number | undefined;
|
|
195
|
-
}>;
|
|
196
|
-
/** moda loop <detectionId> — single loop detection detail. */
|
|
197
|
-
export declare const LoopDetailSchema: z.ZodObject<{
|
|
198
|
-
detection_id: z.ZodString;
|
|
199
|
-
}, "strip", z.ZodTypeAny, {
|
|
200
|
-
detection_id: string;
|
|
201
|
-
}, {
|
|
202
|
-
detection_id: string;
|
|
203
|
-
}>;
|
|
204
188
|
//# sourceMappingURL=schemas.d.ts.map
|
package/dist/schemas.js
CHANGED
|
@@ -92,12 +92,4 @@ export const SearchSchema = z.object({
|
|
|
92
92
|
time_range: z.enum(TIME_RANGES).default('all').optional(),
|
|
93
93
|
limit: z.number().min(1).max(100).default(20).optional(),
|
|
94
94
|
});
|
|
95
|
-
/** moda loops — currently active loop detections. */
|
|
96
|
-
export const LoopsSchema = z.object({
|
|
97
|
-
limit: z.number().min(1).max(200).default(25).optional(),
|
|
98
|
-
});
|
|
99
|
-
/** moda loop <detectionId> — single loop detection detail. */
|
|
100
|
-
export const LoopDetailSchema = z.object({
|
|
101
|
-
detection_id: z.string().uuid({ message: 'detection_id must be a UUID' }),
|
|
102
|
-
});
|
|
103
95
|
//# sourceMappingURL=schemas.js.map
|
package/dist/tui.js
CHANGED
|
@@ -298,7 +298,6 @@ function overviewSignals(record) {
|
|
|
298
298
|
['Frustrations', valueAt(record, ['frustrations', 'total']) ?? record.frustrations],
|
|
299
299
|
['Runs', valueAt(record, ['runs', 'total']) ?? record.runs],
|
|
300
300
|
['Workflows', valueAt(record, ['workflows', 'total']) ?? record.workflows],
|
|
301
|
-
['Loops', valueAt(record, ['loops', 'active']) ?? valueAt(record, ['loops', 'total']) ?? record.loops],
|
|
302
301
|
];
|
|
303
302
|
return candidates
|
|
304
303
|
.map(([label, value]) => [label, metricText(value)])
|
package/package.json
CHANGED
package/skills/moda-cli/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: moda-cli
|
|
3
3
|
version: 2.1.0
|
|
4
|
-
description: Query Moda's AI agent conversation 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,
|
|
4
|
+
description: Query Moda's AI agent conversation 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, and moda prompts status/sync/promote. Use when the user asks about moda, modaflows, conversation analytics, prompt management, user frustrations, agent observability, tool failure debugging, wants to find conversations or tool calls about a topic, or wants to investigate how their AI agent is performing.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Moda CLI
|
|
@@ -475,7 +475,7 @@ Data API fallback. Abbreviated envelope:
|
|
|
475
475
|
```
|
|
476
476
|
|
|
477
477
|
`moda investigate` also accepts scoping flags (`--tool`, `--run`,
|
|
478
|
-
`--conversation
|
|
478
|
+
`--conversation`) to focus the ranking on one signal.
|
|
479
479
|
|
|
480
480
|
### 3. Browse topic clusters
|
|
481
481
|
|
|
@@ -578,21 +578,7 @@ Pass `--include-window` to attach a `window` field per row with the message
|
|
|
578
578
|
slice centered on the anchor. `--window=N` (1–5, default `1`) is the
|
|
579
579
|
half-width; `--window=1` ⇒ 3 messages total (anchor ± 1).
|
|
580
580
|
|
|
581
|
-
### 7.
|
|
582
|
-
|
|
583
|
-
```bash
|
|
584
|
-
moda loops # everything currently stuck
|
|
585
|
-
moda loops --limit=10
|
|
586
|
-
moda loop <detection_id> # one loop signature in detail
|
|
587
|
-
```
|
|
588
|
-
|
|
589
|
-
Loops are detected in real time by the conversation worker (tier 0/1) and
|
|
590
|
-
the analytics container (tier 2). A row with `cycle_visits=378` means the
|
|
591
|
-
agent re-ran the same action 378 times. Use the `loop_signature_human`
|
|
592
|
-
field to recognize cross-conversation patterns (one tool definition bug
|
|
593
|
-
will produce identical signatures across many users).
|
|
594
|
-
|
|
595
|
-
### 8. Prompt management
|
|
581
|
+
### 7. Prompt management
|
|
596
582
|
|
|
597
583
|
Use these only when working on the code-first prompt registry.
|
|
598
584
|
|
|
@@ -762,8 +748,6 @@ npx: `npx -p @moda-ai/cli moda <command>`.
|
|
|
762
748
|
| `moda frustrations` | User frustration detections with evidence |
|
|
763
749
|
| `moda tool-failures` | Tool failure overview |
|
|
764
750
|
| `moda tool-failure-detail <tool_name>` | Per-tool failure breakdown + examples |
|
|
765
|
-
| `moda loops` | Currently-active loop detections |
|
|
766
|
-
| `moda loop <detection_id>` | One loop signature with blast radius |
|
|
767
751
|
| `moda prompts status` | Read-only local prompt status |
|
|
768
752
|
| `moda prompts diff` | Read-only local prompt diff/status |
|
|
769
753
|
| `moda prompts sync` | Upload changed prompt versions and update lockfile |
|