@moda-ai/cli 1.55.107 → 1.55.109

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 (47) hide show
  1. package/README.md +3 -3
  2. package/dist/{agent-s7y4147m.js → agent-5kfdbx36.js} +9 -9
  3. package/dist/{change-impact-4kafnhjs.js → change-impact-v2vbcphy.js} +6 -6
  4. package/dist/cli-2fv0q9tx.js +141 -0
  5. package/dist/{cli-wds9vyfc.js → cli-3r578f36.js} +6 -6
  6. package/dist/{cli-13zdcv4w.js → cli-3thzh1mq.js} +1 -1
  7. package/dist/{cli-998n4kz9.js → cli-6df723jn.js} +1 -1
  8. package/dist/{cli-zhytd6vx.js → cli-6zmc6asf.js} +7 -7
  9. package/dist/{cli-ap7wfbnk.js → cli-7gnw6smk.js} +2 -2
  10. package/dist/{cli-ctt5e18a.js → cli-84jkd2x7.js} +14 -14
  11. package/dist/{cli-mc3z77bv.js → cli-8qtxp95w.js} +1 -1
  12. package/dist/cli-ahqr7wsp.js +429 -0
  13. package/dist/{cli-qwnkv4jy.js → cli-bgbtrmtr.js} +1 -1
  14. package/dist/{cli-n9ng8mym.js → cli-cp8gv24j.js} +1 -1
  15. package/dist/{cli-p62hq2sh.js → cli-ew4pkn5b.js} +7 -7
  16. package/dist/{cli-00pnbffb.js → cli-hv4bztsm.js} +1 -1
  17. package/dist/{cli-62e1vy8f.js → cli-m6w66x9d.js} +3 -3
  18. package/dist/{cli-37z2f5wa.js → cli-mh94f7gp.js} +4 -9
  19. package/dist/{cli-51zgnfvk.js → cli-rpyepjwb.js} +1 -1
  20. package/dist/{cli-1nd4339b.js → cli-tca7sztv.js} +2 -2
  21. package/dist/cli.js +29 -131
  22. package/dist/{doctor-9bwwb3qh.js → doctor-t0b99wnq.js} +8 -8
  23. package/dist/{harness-github-actions-hnn2qhew.js → harness-github-actions-e4zrcrym.js} +6 -6
  24. package/dist/{harness-vvzq3b7j.js → harness-phdj0eqr.js} +6 -6
  25. package/dist/{index-54s9qh63.js → index-65grk0mp.js} +6 -6
  26. package/dist/{index-xz7gvfhc.js → index-86wb6vbh.js} +7 -7
  27. package/dist/{index-pehbgwrh.js → index-zhg2zc3x.js} +14 -14
  28. package/dist/{production-intelligence-8w7an97c.js → production-intelligence-31p18dfx.js} +3 -3
  29. package/dist/{profile-commands-zgq8dja0.js → profile-commands-tz3jykvh.js} +4 -4
  30. package/dist/{prompt-attribution-245m798r.js → prompt-attribution-8ak38a3q.js} +6 -6
  31. package/dist/prompt-source-mcp.js +6 -6
  32. package/dist/{prompts-vay4denw.js → prompts-a8zcvc1c.js} +5 -5
  33. package/dist/{provision-d0sxcka1.js → provision-2dzzb0be.js} +5 -5
  34. package/dist/{registry-w50mdzsb.js → registry-p07epn79.js} +22 -18
  35. package/dist/skills-5atq9sgh.js +17 -0
  36. package/dist/{skills-bundled-7jes6hqx.js → skills-bundled-tcxpw88n.js} +2 -2
  37. package/dist/{sync-s64t7fas.js → sync-e76vmfty.js} +11 -13
  38. package/package.json +1 -1
  39. package/skills/integration/index.json +2 -2
  40. package/skills/moda-cli/SKILL.md +1 -1
  41. package/skills/moda-cli/references/commands.md +2 -2
  42. package/skills/moda-cli/references/dashboard-parity.md +1 -1
  43. package/skills/moda-cli/references/output-protocol.md +4 -4
  44. package/skills/moda-cli/references/registry.md +1 -3
  45. package/dist/cli-0mnbxftj.js +0 -1019
  46. package/dist/cli-qm5b1vck.js +0 -220
  47. package/dist/skills-nrn4bqc3.js +0 -23
@@ -0,0 +1,429 @@
1
+ import {
2
+ readSkillsManifest
3
+ } from "./cli-2fv0q9tx.js";
4
+ import {
5
+ createCommandContext
6
+ } from "./cli-3thzh1mq.js";
7
+ import {
8
+ assertFlags,
9
+ assertPositionals
10
+ } from "./cli-mh94f7gp.js";
11
+ import {
12
+ callControlAPI
13
+ } from "./cli-cp8gv24j.js";
14
+ import {
15
+ CliInputError
16
+ } from "./cli-k4tqwah4.js";
17
+ import {
18
+ __require
19
+ } from "./cli-0v6na3yp.js";
20
+
21
+ // src/skills.ts
22
+ import { execFileSync } from "node:child_process";
23
+ import { createHash } from "node:crypto";
24
+ import { existsSync as existsSync2, lstatSync as lstatSync2, readdirSync, readFileSync as readFileSync2 } from "node:fs";
25
+ import { basename, dirname as dirname2, join as join2, relative } from "node:path";
26
+
27
+ // src/agents-md.ts
28
+ import { existsSync, lstatSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
29
+ import { dirname, join } from "node:path";
30
+ var AGENTS_MD_FILENAME = "AGENTS.md";
31
+ var FIXES_BLOCK_BEGIN = "<!-- moda:fixes:begin -->";
32
+ var FIXES_BLOCK_END = "<!-- moda:fixes:end -->";
33
+ function renderFixesBlock() {
34
+ return [
35
+ FIXES_BLOCK_BEGIN,
36
+ "## Fixing production issues with Moda (managed block — edits inside are overwritten by moda-cli)",
37
+ "",
38
+ "Moda supplies the production evidence; you propose and make the fix yourself.",
39
+ "The `moda` CLI needs `MODA_API_KEY` (or `npx -y -p @moda-ai/cli moda ...` when",
40
+ "not installed); `moda <command> --help` lists its flags.",
41
+ "",
42
+ '- Find where something happened in production: `moda traces search "<words>"`, then',
43
+ " `moda traces get <conversation_id> --msg-index=<message_index>` to read the turn.",
44
+ "- Find what to fix: `moda investigate` ranks tool failures, user frustrations,",
45
+ " and top Problems with evidence; `moda problems` ranks cross-signal Problems",
46
+ " by root cause; `moda failures` lists tool failures only.",
47
+ "- Read the evidence before editing: `moda problems get <problem_id>` (dossier),",
48
+ " `moda problems get <problem_id> --evidence` (attribution rationales and anchors),",
49
+ " `moda problems get <problem_id> --traces` (affected traces),",
50
+ " `moda detections tools <tool_name>` (failing calls in context), and",
51
+ " `moda traces get <conversation_id>` (the messages around a turn; `--all` for",
52
+ " the whole trace).",
53
+ "- Propose the change in the code, prompt, tool definition, or skill that",
54
+ " causes the issue, and cite the Moda problem or trace ids it is based on",
55
+ " in the PR description.",
56
+ "- Prompts live in `.moda/prompts.yml` (version 2: `prompt_paths` globs plus",
57
+ " `sources:` mappings for prompts defined in code); after `moda prompts sync`,",
58
+ " pass `prompt: lock.prompts['<key>']` to createThinkTelemetry/createAI7Telemetry.",
59
+ "- After the fix ships, record it with",
60
+ " `moda problems feedback <problem_id> --action=mark_fixed`; if the issue",
61
+ " is detected again, the Problem comes back.",
62
+ FIXES_BLOCK_END
63
+ ].join(`
64
+ `);
65
+ }
66
+ function countOccurrences(text, needle) {
67
+ return text.split(needle).length - 1;
68
+ }
69
+ function upsertManagedBlock(existing, block) {
70
+ if (existing === null) {
71
+ return { ok: true, content: `${block}
72
+ ` };
73
+ }
74
+ const begins = countOccurrences(existing, FIXES_BLOCK_BEGIN);
75
+ const ends = countOccurrences(existing, FIXES_BLOCK_END);
76
+ if (begins === 0 && ends === 0) {
77
+ const separator = existing === "" || existing.endsWith(`
78
+
79
+ `) ? "" : existing.endsWith(`
80
+ `) ? `
81
+ ` : `
82
+
83
+ `;
84
+ return { ok: true, content: `${existing}${separator}${block}
85
+ ` };
86
+ }
87
+ const beginIdx = existing.indexOf(FIXES_BLOCK_BEGIN);
88
+ const endIdx = existing.indexOf(FIXES_BLOCK_END);
89
+ if (begins === 1 && ends === 1 && endIdx > beginIdx) {
90
+ const before = existing.slice(0, beginIdx);
91
+ const after = existing.slice(endIdx + FIXES_BLOCK_END.length);
92
+ return { ok: true, content: `${before}${block}${after}` };
93
+ }
94
+ const problem = begins === 1 && ends === 1 ? `its ${FIXES_BLOCK_END} marker comes before its ${FIXES_BLOCK_BEGIN} marker` : `it has ${begins} ${FIXES_BLOCK_BEGIN} and ${ends} ${FIXES_BLOCK_END} marker(s) instead of one of each`;
95
+ return {
96
+ ok: false,
97
+ reason: `The Moda block in ${AGENTS_MD_FILENAME} was not updated because ${problem}. ` + "The file was left unchanged so no text is lost. Keep exactly one begin marker followed by one end marker " + "(or delete the stray markers), then rerun `moda skills install moda-cli` (or `moda skills push`)."
98
+ };
99
+ }
100
+ function writeFileIfChanged(filePath, content) {
101
+ try {
102
+ mkdirSync(dirname(filePath), { recursive: true });
103
+ if (existsSync(filePath)) {
104
+ const current = readFileSync(filePath, "utf8");
105
+ if (current === content)
106
+ return { status: "unchanged" };
107
+ writeFileSync(filePath, content);
108
+ return { status: "updated" };
109
+ }
110
+ writeFileSync(filePath, content);
111
+ return { status: "wrote" };
112
+ } catch (err) {
113
+ return { status: "failed", error: err instanceof Error ? err.message : String(err) };
114
+ }
115
+ }
116
+ function upsertFixesAgentsBlock(cwd) {
117
+ const filePath = join(cwd, AGENTS_MD_FILENAME);
118
+ let existing = null;
119
+ try {
120
+ if (lstatSync(filePath).isSymbolicLink()) {
121
+ return { path: AGENTS_MD_FILENAME, status: "skipped", reason: "AGENTS.md is a symlink and was left unchanged. Update the linked file manually, or replace the link with a project file and rerun `moda skills install moda-cli`." };
122
+ }
123
+ } catch (err) {
124
+ if (err.code !== "ENOENT") {
125
+ return { path: AGENTS_MD_FILENAME, status: "failed", reason: `Could not inspect ${AGENTS_MD_FILENAME}: ${err instanceof Error ? err.message : String(err)}` };
126
+ }
127
+ }
128
+ if (existsSync(filePath)) {
129
+ try {
130
+ existing = readFileSync(filePath, "utf8");
131
+ } catch (err) {
132
+ return {
133
+ path: AGENTS_MD_FILENAME,
134
+ status: "failed",
135
+ reason: `Could not read ${AGENTS_MD_FILENAME}: ${err instanceof Error ? err.message : String(err)}`
136
+ };
137
+ }
138
+ }
139
+ const next = upsertManagedBlock(existing, renderFixesBlock());
140
+ if (!next.ok)
141
+ return { path: AGENTS_MD_FILENAME, status: "skipped", reason: next.reason };
142
+ const written = writeFileIfChanged(filePath, next.content);
143
+ return {
144
+ path: AGENTS_MD_FILENAME,
145
+ status: written.status,
146
+ ...written.error ? { reason: `Could not write ${AGENTS_MD_FILENAME}: ${written.error}` } : {}
147
+ };
148
+ }
149
+ function agentsMdProblem(agentsMd) {
150
+ if (!agentsMd || agentsMd.status !== "skipped" && agentsMd.status !== "failed")
151
+ return;
152
+ return agentsMd.reason ?? `The Moda block in ${agentsMd.path} could not be updated.`;
153
+ }
154
+
155
+ // src/skills.ts
156
+ var SKILLS_DIR = join2(".claude", "skills");
157
+ var SKILL_FILE = "SKILL.md";
158
+ var MAX_SKILL_WALK_DEPTH = 4;
159
+ async function runSkillSync(flags = {}, profileOptions = {}, options = {}) {
160
+ const cwd = options.cwd ?? process.cwd();
161
+ const dryRun = flags["dry-run"] === "true";
162
+ const agentsMd = dryRun ? undefined : upsertFixesAgentsBlock(cwd);
163
+ const skills = discoverLocalSkills(cwd);
164
+ if (skills.length === 0) {
165
+ return { synced: [], dryRun, ...agentsMd ? { agentsMd } : {} };
166
+ }
167
+ const sourceCommit = getGitCommit(cwd);
168
+ const response = await callControlAPI("/skills/sync", {
169
+ method: "POST",
170
+ body: JSON.stringify({
171
+ skills: skills.map((skill) => ({
172
+ key: skill.key,
173
+ name: skill.name,
174
+ description: skill.description,
175
+ skillMd: skill.skillMd,
176
+ sourcePath: skill.sourcePath,
177
+ contentHash: skill.contentHash,
178
+ sourceCommit
179
+ })),
180
+ sourceCommit,
181
+ dryRun
182
+ })
183
+ }, profileOptions);
184
+ return { synced: response.synced ?? [], dryRun, ...agentsMd ? { agentsMd } : {} };
185
+ }
186
+ function discoverLocalSkills(cwd) {
187
+ const skillsRoot = join2(cwd, SKILLS_DIR);
188
+ if (!existsSync2(skillsRoot))
189
+ return [];
190
+ const managed = new Set(managedSkillPaths(cwd));
191
+ const skills = [];
192
+ for (const absPath of walkSkillFiles(skillsRoot, 0)) {
193
+ const sourcePath = relative(cwd, absPath).replace(/\\/g, "/");
194
+ if (managed.has(sourcePath))
195
+ continue;
196
+ const key = basename(dirname2(absPath));
197
+ if (key === "moda-cli" || !/^[A-Za-z0-9_-]+$/.test(key))
198
+ continue;
199
+ let content;
200
+ try {
201
+ content = readFileSync2(absPath, "utf8");
202
+ } catch {
203
+ continue;
204
+ }
205
+ if (!content.trim())
206
+ continue;
207
+ const { name, description } = parseSkillFrontmatter(content, key);
208
+ skills.push({
209
+ key,
210
+ name,
211
+ description,
212
+ skillMd: content,
213
+ sourcePath,
214
+ contentHash: sha256(content)
215
+ });
216
+ }
217
+ return skills.sort((a, b) => a.key.localeCompare(b.key));
218
+ }
219
+ function managedSkillPaths(cwd) {
220
+ const manifest = readSkillsManifest(cwd);
221
+ if (!manifest)
222
+ return [];
223
+ return manifest.managedPaths.filter((path) => path.startsWith(".claude/skills/") && path.endsWith("/SKILL.md"));
224
+ }
225
+ function walkSkillFiles(dir, depth) {
226
+ if (depth > MAX_SKILL_WALK_DEPTH)
227
+ return [];
228
+ let entries;
229
+ try {
230
+ entries = readdirSync(dir);
231
+ } catch {
232
+ return [];
233
+ }
234
+ const files = [];
235
+ for (const entry of entries) {
236
+ const fullPath = join2(dir, entry);
237
+ let stat;
238
+ try {
239
+ stat = lstatSync2(fullPath);
240
+ } catch {
241
+ continue;
242
+ }
243
+ if (stat.isSymbolicLink())
244
+ continue;
245
+ if (stat.isDirectory()) {
246
+ files.push(...walkSkillFiles(fullPath, depth + 1));
247
+ } else if (stat.isFile() && entry === SKILL_FILE) {
248
+ files.push(fullPath);
249
+ }
250
+ }
251
+ return files;
252
+ }
253
+ function parseSkillFrontmatter(raw, fallbackKey) {
254
+ let name = fallbackKey;
255
+ let description;
256
+ if (raw.startsWith("---")) {
257
+ const end = raw.indexOf(`
258
+ ---`, 3);
259
+ if (end !== -1) {
260
+ const frontmatter = raw.slice(3, end);
261
+ const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
262
+ const descMatch = frontmatter.match(/^description:\s*(.+)$/m);
263
+ if (nameMatch)
264
+ name = stripQuotes(nameMatch[1].trim()) || fallbackKey;
265
+ if (descMatch)
266
+ description = stripQuotes(descMatch[1].trim()) || undefined;
267
+ }
268
+ }
269
+ return { name, description };
270
+ }
271
+ function stripQuotes(value) {
272
+ return value.replace(/^["']|["']$/g, "");
273
+ }
274
+ function getGitCommit(cwd) {
275
+ try {
276
+ return execFileSync("git", ["rev-parse", "HEAD"], {
277
+ cwd,
278
+ encoding: "utf8",
279
+ stdio: ["ignore", "pipe", "ignore"]
280
+ }).trim();
281
+ } catch {
282
+ return;
283
+ }
284
+ }
285
+ var SKILLS_SUBCOMMAND_FLAGS = {
286
+ install: ["list"]
287
+ };
288
+ async function runSkillsCommand(input) {
289
+ const context = "output" in input ? input : createCommandContext({
290
+ command: input.command,
291
+ positional: input.positional,
292
+ positionals: input.positionals,
293
+ flags: input.flags
294
+ }, {
295
+ outputMode: input.flags.agent === "true" ? "agent" : input.flags.json === "true" ? "json" : "human"
296
+ });
297
+ const sub = context.positional;
298
+ const positionals = context.positionals ?? (sub ? [sub] : []);
299
+ const flags = context.flags;
300
+ if (sub && SKILLS_SUBCOMMAND_FLAGS[sub])
301
+ assertFlags(`skills ${sub}`, flags, SKILLS_SUBCOMMAND_FLAGS[sub]);
302
+ if (sub === "list" || sub === "show") {
303
+ return runSkillRegistryCommand(sub, positionals, flags, context);
304
+ }
305
+ if (sub === "sync") {
306
+ assertFlags("skills sync", flags, ["dry-run"]);
307
+ const result = await runSkillSync(flags, { profile: context.profile, env: context.env });
308
+ const agentsMdWarning = agentsMdProblem(result.agentsMd);
309
+ context.output.writeData({
310
+ synced: result.synced,
311
+ dryRun: result.dryRun,
312
+ ...result.agentsMd ? { agentsMd: result.agentsMd } : {}
313
+ }, agentsMdWarning ? { status: "degraded", warnings: [agentsMdWarning] } : {});
314
+ return 0;
315
+ }
316
+ if (sub === "install") {
317
+ return runSkillsInstall(context, positionals.slice(1));
318
+ }
319
+ throw new CliInputError(sub ? `Unknown skills subcommand '${sub}'` : "A skills subcommand is required", "Usage: moda skills list | moda skills show <key> | moda skills push [--dry-run] | moda skills install [--list] <id...>");
320
+ }
321
+ function sha256(input) {
322
+ return createHash("sha256").update(input).digest("hex");
323
+ }
324
+ var MODA_CLI_SKILL_ID = "moda-cli";
325
+ async function installModaCliSkill(context) {
326
+ const { detectAgents } = await import("./mcp-1qre9f0n.js");
327
+ const { installRules, summarizeInstall } = await import("./rules-qddx5t0j.js");
328
+ const result = await installRules(detectAgents(), { yes: true, silent: true });
329
+ if (result.status === "skipped") {
330
+ throw new CliInputError("No supported coding agent was detected here, so the moda-cli skill was not installed.", "Run this from a project with a .claude or .cursor directory, or with Claude Code on PATH. Only Claude Code and Cursor are supported.");
331
+ }
332
+ const agentsMd = result.status === "failed" ? undefined : upsertFixesAgentsBlock(context.cwd);
333
+ const blockWarning = agentsMdProblem(agentsMd);
334
+ if (blockWarning) {
335
+ result.warnings.push(blockWarning);
336
+ result.status = "warning";
337
+ }
338
+ const summary = summarizeInstall(result);
339
+ if (context.outputMode !== "human") {
340
+ context.output.writeData({ skill: MODA_CLI_SKILL_ID, status: result.status, agents: result.agents, counts: result.counts, summary, outcomes: result.outcomes, notes: result.notes, agentsMd }, { ...result.status === "failed" ? { status: "error" } : {}, warnings: result.warnings });
341
+ } else {
342
+ console.log(`moda-cli skill for ${result.agents.join(", ")}: ${summary}`);
343
+ for (const note of result.notes)
344
+ console.log(` ${note}`);
345
+ for (const warning of result.warnings)
346
+ console.error(` ${warning}`);
347
+ }
348
+ return result.status === "failed" ? 1 : 0;
349
+ }
350
+ async function runSkillsInstall(context, ids) {
351
+ const { installIntegrationSkill, readBundledIndex, readBundledSkillMd } = await import("./skills-bundled-tcxpw88n.js");
352
+ const index = readBundledIndex();
353
+ if (context.flags.list === "true" || ids.length === 0) {
354
+ const { bundledSkillVersion } = await import("./rules-qddx5t0j.js");
355
+ if (!index) {
356
+ throw new CliInputError("This CLI build has no bundled integration guides", "Install a published @moda-ai/cli, or run `bun run bundle:skills` in apps/moda-cli.");
357
+ }
358
+ const skills = [
359
+ { id: MODA_CLI_SKILL_ID, version: bundledSkillVersion(MODA_CLI_SKILL_ID), language: "any", summary: "This CLI's own guide for coding agents; installs or refreshes it for each detected agent (copies edited locally are kept)." },
360
+ ...index.skills.map((skill) => ({
361
+ id: skill.id,
362
+ version: skill.version,
363
+ language: skill.targets.language,
364
+ summary: skill.summary
365
+ }))
366
+ ];
367
+ if (context.outputMode !== "human") {
368
+ context.output.writeData({ skills });
369
+ } else {
370
+ for (const skill of skills)
371
+ console.log(`${skill.id} ${skill.version} ${skill.summary}`);
372
+ if (ids.length === 0 && context.flags.list !== "true") {
373
+ console.error("Install one or more with: moda skills install <id...>");
374
+ }
375
+ }
376
+ return 0;
377
+ }
378
+ if (ids.includes(MODA_CLI_SKILL_ID)) {
379
+ const others = ids.filter((id) => id !== MODA_CLI_SKILL_ID);
380
+ if (others.length > 0) {
381
+ throw new CliInputError(`Install ${MODA_CLI_SKILL_ID} on its own, so nothing was written.`, `Run \`moda skills install ${MODA_CLI_SKILL_ID}\`, then \`moda skills install ${others.join(" ")}\`.`);
382
+ }
383
+ return installModaCliSkill(context);
384
+ }
385
+ const unknown = ids.filter((id) => !/^[a-z0-9-]+$/.test(id) || readBundledSkillMd(id) === null);
386
+ if (unknown.length > 0) {
387
+ throw new CliInputError(`Not bundled with this CLI: ${unknown.map((id) => JSON.stringify(id).slice(0, 80)).join(", ")}`, "List the bundled guides with: moda skills install --list");
388
+ }
389
+ const results = [];
390
+ for (const id of ids) {
391
+ try {
392
+ results.push(installIntegrationSkill(id));
393
+ } catch (error) {
394
+ const done = results.map((result) => result.skillId);
395
+ throw new CliInputError(error instanceof Error ? error.message : String(error), done.length > 0 ? `Already installed before the failure: ${done.join(", ")}. Fix the error and rerun; installed guides are left as they are.` : "List the bundled guides with: moda skills install --list");
396
+ }
397
+ }
398
+ if (context.outputMode !== "human") {
399
+ context.output.writeData({ installed: results });
400
+ } else {
401
+ for (const result of results) {
402
+ console.log(`${result.status} ${result.skillId}`);
403
+ for (const path of result.paths)
404
+ console.log(` ${path}`);
405
+ }
406
+ }
407
+ return 0;
408
+ }
409
+ var RESERVED_SKILL_PATHS = new Set(["sync"]);
410
+ async function runSkillRegistryCommand(sub, positionals, flags, context) {
411
+ const profileOptions = { profile: context.profile, env: context.env };
412
+ assertFlags(`skills ${sub}`, flags, []);
413
+ assertPositionals(`skills ${sub}`, positionals, sub === "list" ? 1 : 2, sub === "list" ? "moda skills list" : "moda skills show <key>");
414
+ if (sub === "list") {
415
+ context.output.writeData(await callControlAPI("/skills", {}, profileOptions));
416
+ return 0;
417
+ }
418
+ const idOrKey = positionals[1];
419
+ if (!idOrKey) {
420
+ throw new CliInputError("A skill key or id is required for skills show.", "Usage: moda skills show <key>");
421
+ }
422
+ if (RESERVED_SKILL_PATHS.has(idOrKey)) {
423
+ throw new CliInputError(`'${idOrKey}' is a reserved path, so this skill must be addressed by its id.`, "Find the id (skill_…) with `moda skills list`, then pass that instead of the key.");
424
+ }
425
+ context.output.writeData(await callControlAPI(`/skills/${encodeURIComponent(idOrKey)}`, {}, profileOptions));
426
+ return 0;
427
+ }
428
+
429
+ export { agentsMdProblem, runSkillSync, runSkillsCommand };
@@ -6,7 +6,7 @@ import {
6
6
  saveProfileConfig,
7
7
  secretFilePathFromRef,
8
8
  writeSecretJsonFile
9
- } from "./cli-1nd4339b.js";
9
+ } from "./cli-tca7sztv.js";
10
10
  import {
11
11
  CliAuthError,
12
12
  CliInputError
@@ -4,7 +4,7 @@ import {
4
4
  recordApiRequest,
5
5
  resolveApiKey,
6
6
  resolveModaBaseUrl
7
- } from "./cli-1nd4339b.js";
7
+ } from "./cli-tca7sztv.js";
8
8
 
9
9
  // src/api-client.ts
10
10
  var REQUEST_TIMEOUT_MS = 30000;
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  isAuthSessionValid,
3
3
  loadAuthSession
4
- } from "./cli-qwnkv4jy.js";
4
+ } from "./cli-bgbtrmtr.js";
5
5
  import {
6
6
  inspectPromptManifest
7
- } from "./cli-wds9vyfc.js";
7
+ } from "./cli-3r578f36.js";
8
8
  import {
9
9
  readHarnessSyncState,
10
10
  renderDoctorHuman,
11
11
  renderStatusHuman
12
- } from "./cli-51zgnfvk.js";
12
+ } from "./cli-rpyepjwb.js";
13
13
  import {
14
14
  callDataAPI
15
- } from "./cli-n9ng8mym.js";
15
+ } from "./cli-cp8gv24j.js";
16
16
  import {
17
17
  describeModaBaseUrl,
18
18
  ensureSecretFilePermissions,
@@ -27,7 +27,7 @@ import {
27
27
  resolveSecretReference,
28
28
  resolveTenantId,
29
29
  secretFilePathFromRef
30
- } from "./cli-1nd4339b.js";
30
+ } from "./cli-tca7sztv.js";
31
31
  import {
32
32
  __require
33
33
  } from "./cli-0v6na3yp.js";
@@ -179,7 +179,7 @@ async function buildDoctorReport(context, options) {
179
179
  "skills",
180
180
  ".claude/skills",
181
181
  ".cursor/rules"
182
- ], "moda skills pull"));
182
+ ]));
183
183
  checks.push(discoveryCheck("evals_discovered", "harness", "Evals/tests are discovered", context.cwd, [
184
184
  "evals",
185
185
  "tests",
@@ -393,7 +393,7 @@ async function harnessCurrentCheck(cwd, manifestPath, manifestExists, tenantId)
393
393
  };
394
394
  }
395
395
  try {
396
- const { scanHarness } = await import("./harness-vvzq3b7j.js");
396
+ const { scanHarness } = await import("./harness-phdj0eqr.js");
397
397
  const current = scanHarness({
398
398
  rootDir: cwd,
399
399
  scannerVersion: "doctor",
@@ -21,7 +21,7 @@ import {
21
21
  valueDeclaration,
22
22
  visit,
23
23
  workspacePackages
24
- } from "./cli-ctt5e18a.js";
24
+ } from "./cli-84jkd2x7.js";
25
25
  import {
26
26
  require_typescript
27
27
  } from "./cli-r0pkdy83.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  fetchApiKeyProbe
3
- } from "./cli-998n4kz9.js";
3
+ } from "./cli-6df723jn.js";
4
4
  import {
5
5
  authFetch,
6
6
  getCachedLoginContext
7
- } from "./cli-qwnkv4jy.js";
7
+ } from "./cli-bgbtrmtr.js";
8
8
  import {
9
9
  embeddedTenantIdFromApiKey,
10
10
  getModaDir,
@@ -15,7 +15,7 @@ import {
15
15
  resolveTenantIdFromActiveProfile,
16
16
  saveCliConfig,
17
17
  writeSecretJsonFile
18
- } from "./cli-1nd4339b.js";
18
+ } from "./cli-tca7sztv.js";
19
19
  import {
20
20
  CliAccessError,
21
21
  CliInputError,
@@ -2,7 +2,7 @@ import {
2
2
  ApiError,
3
3
  callControlAPI,
4
4
  callDataAPI
5
- } from "./cli-n9ng8mym.js";
5
+ } from "./cli-cp8gv24j.js";
6
6
  import {
7
7
  continuationCommand,
8
8
  embeddedTenantIdFromApiKey,
@@ -11,7 +11,7 @@ import {
11
11
  resolveApiTenantId,
12
12
  setPlatformTenantOverride,
13
13
  shellArg
14
- } from "./cli-1nd4339b.js";
14
+ } from "./cli-tca7sztv.js";
15
15
  import {
16
16
  CliAccessError,
17
17
  CliInputError
@@ -74,7 +74,7 @@ var ConversationsSchema = z.object({
74
74
  until: isoBoundFlag().describe("Absolute UTC end, inclusive (ISO date or datetime; a date covers that whole day)"),
75
75
  environment: z.enum(["all", "development", "staging", "production"]).default("all").optional().describe("Only traces from this environment"),
76
76
  world_state: z.string().max(200).optional().describe("Match world-state content (slots + durable profile); comma = AND"),
77
- outcome: z.enum(["any", "positive", "negative"]).default("any").optional().describe("Filter by trace outcome (trajectory + frustration)"),
77
+ outcome: z.enum(["any", "positive", "negative"]).default("any").optional().describe("Filter by trace outcome: negative = a frustration was detected in the trace, positive = no frustration detected"),
78
78
  include_world_state: boolFlag().describe("Attach each result's world-state summary"),
79
79
  sort: z.enum(["recent", "longest", "slowest"]).optional().describe("recent = newest activity, longest = most messages, slowest = longest span"),
80
80
  cohort: cohortFlag("Only traces of this cohort's current members (builtin:<key> or a saved cohort id)"),
@@ -187,7 +187,6 @@ var REMAINDER_FAMILIES = [
187
187
  "emotion",
188
188
  "laziness",
189
189
  "hallucination",
190
- "prm_dip",
191
190
  "custom_signal",
192
191
  "conversation_reader"
193
192
  ];
@@ -403,9 +402,6 @@ var LazinessSchema = z.object({
403
402
  order: z.enum(SORT_ORDERS).optional().describe("Sort direction (default desc)"),
404
403
  cohort: cohortFlag("Only traces of this cohort's members (builtin:<key> or a saved cohort id); not with --conversation-id")
405
404
  });
406
- var StepScoresSchema = z.object({
407
- conversation_id: z.string().min(1).describe("Trace ID")
408
- });
409
405
  var TAIL_SIGNALS = ["traces", "conversations", "emotions", "all"];
410
406
  var TailSchema = z.object({
411
407
  interval: z.number().int().min(5).max(3600).default(15).optional().describe("Seconds between polls"),
@@ -776,7 +772,6 @@ var COMMAND_FLAG_SPECS = {
776
772
  emotions: { schema: EmotionsSchema },
777
773
  laziness: { schema: LazinessSchema },
778
774
  hallucinations: { schema: HallucinationsSchema },
779
- "step-scores": { schema: StepScoresSchema, handParsed: true, positionals: [TRACE_ID] },
780
775
  tail: { schema: TailSchema },
781
776
  feedback: {
782
777
  schema: FeedbackSchema,
@@ -1664,4 +1659,4 @@ function unknownSignalsSubcommandError(sub, args = []) {
1664
1659
  ${SIGNAL_USAGE}`);
1665
1660
  }
1666
1661
 
1667
- export { CLUSTER_COHORT_TIME_RANGES, TRACE_GRAIN_FLAGS, MAX_CONVERSATION_IDS_FILTER, BOOK_PROBLEM_SORTS, DREAM_PROBLEM_SORTS, PROBLEMS_MAX_LIMIT, PROBLEMS_DEFAULT_LIMIT, ProblemsRemainderSchema, UUID_RE, ProblemImpactSchema, PROBLEM_FEEDBACK_ACTIONS, ProblemFeedbackSchema, ProblemLinearFileSchema, SignalLabelSchema, DETECTION_VERDICTS, DetectionReviewSchema, FALSE_POSITIVE_KINDS, FalsePositiveSchema, EMOTION_FAMILIES, LAZINESS_FAMILIES, StepScoresSchema, AuditSchema, TraceFindingsSchema, FEEDBACK_USAGE, isFeedbackRefFlag, buildFeedbackRequest, writeDryRun, COMMAND_FLAG_SPECS, flagSpecFor, kebabFlag, schemaShape, describeField, specFlagKeys, specFlagNames, describeSpecFlags, closestMatches, usageLine, renderFlagHelp, subcommandHelpFlags, manifestFlagFields, requireTenant, assertFlags, assertPositionals, runUsersCommand, runUserCommand, runCohortCommand, runProblemReopenCommand, runSignalsManagementCommand, SIGNALS_MANAGEMENT_SUBCOMMANDS, unknownSignalsSubcommandError };
1662
+ export { CLUSTER_COHORT_TIME_RANGES, TRACE_GRAIN_FLAGS, MAX_CONVERSATION_IDS_FILTER, BOOK_PROBLEM_SORTS, DREAM_PROBLEM_SORTS, PROBLEMS_MAX_LIMIT, PROBLEMS_DEFAULT_LIMIT, ProblemsRemainderSchema, UUID_RE, ProblemImpactSchema, PROBLEM_FEEDBACK_ACTIONS, ProblemFeedbackSchema, ProblemLinearFileSchema, SignalLabelSchema, DETECTION_VERDICTS, DetectionReviewSchema, FALSE_POSITIVE_KINDS, FalsePositiveSchema, EMOTION_FAMILIES, LAZINESS_FAMILIES, AuditSchema, TraceFindingsSchema, FEEDBACK_USAGE, isFeedbackRefFlag, buildFeedbackRequest, writeDryRun, COMMAND_FLAG_SPECS, flagSpecFor, kebabFlag, schemaShape, describeField, specFlagKeys, specFlagNames, describeSpecFlags, closestMatches, usageLine, renderFlagHelp, subcommandHelpFlags, manifestFlagFields, requireTenant, assertFlags, assertPositionals, runUsersCommand, runUserCommand, runCohortCommand, runProblemReopenCommand, runSignalsManagementCommand, SIGNALS_MANAGEMENT_SUBCOMMANDS, unknownSignalsSubcommandError };
@@ -23,7 +23,7 @@ var messaging_default = {
23
23
  "apps/moda-frontend/content/llms/homepage.md",
24
24
  "apps/moda-frontend/app/llms.txt/route.ts (summary line)",
25
25
  "docs/index.mdx frontmatter description",
26
- "AGENTS.md and .cursorrules (What Moda Is)",
26
+ ".cursorrules (What Moda Is)",
27
27
  "Y Combinator company page one-liner"
28
28
  ]
29
29
  },
@@ -768,8 +768,8 @@ var LEGACY_NAMES = [
768
768
  { legacy: "signal-label", use: "moda review custom-signal <signal_id> --verdict=correct|false_positive", canonical: { command: "review", subcommand: "custom-signal" } },
769
769
  { legacy: "false-positives", use: "moda reviews list", canonical: { command: "reviews", subcommand: "list" } },
770
770
  { legacy: "detection-reviews", use: "moda reviews list <conversation_id> --kind=problem-detection", canonical: { command: "reviews", subcommand: "list" } },
771
- { 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')." },
772
- { 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)." }
771
+ { legacy: "skills sync", use: "moda skills push", canonical: { command: "skills", subcommand: "push" }, note: "It uploads local SKILL.md files." },
772
+ { legacy: "sync skills", use: "moda skills push", canonical: { command: "skills", subcommand: "push" }, note: "It uploads local SKILL.md files." }
773
773
  ];
774
774
  var byLegacy = new Map(LEGACY_NAMES.map((entry) => [entry.legacy, entry]));
775
775
  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");