@moda-ai/cli 1.43.1 → 1.44.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.
@@ -29,6 +29,8 @@ import {
29
29
  } from "./cli-rycpwqzm.js";
30
30
  import {
31
31
  CliInputError,
32
+ EXIT_ERROR,
33
+ EXIT_OK,
32
34
  createCommandContext,
33
35
  ensureSecretFilePermissions,
34
36
  getActiveProfile,
@@ -5662,7 +5664,7 @@ async function runPromptAb(flags, profileOptions, context) {
5662
5664
  message: enqueue.message ?? "Replay comparison queued",
5663
5665
  plannedPlayouts
5664
5666
  }, writeOptions);
5665
- return;
5667
+ return EXIT_OK;
5666
5668
  }
5667
5669
  const deadline = Date.now() + timeoutMs;
5668
5670
  let latest = null;
@@ -5696,7 +5698,9 @@ async function runPromptAb(flags, profileOptions, context) {
5696
5698
  if (context.outputMode === "human") {
5697
5699
  printHumanVerdict(result);
5698
5700
  }
5699
- context.output.writeData(result, writeOptions);
5701
+ const failed = result.status === "error";
5702
+ context.output.writeData(result, { ...writeOptions, ...failed ? { status: "error" } : {} });
5703
+ return failed ? EXIT_ERROR : EXIT_OK;
5700
5704
  } catch (error) {
5701
5705
  if (warnings.length && error && typeof error === "object") {
5702
5706
  Object.assign(error, { warnings });
@@ -6608,8 +6612,7 @@ async function runPromptsCommand(input, legacyFlags, legacyProfileOptions) {
6608
6612
  await promotePrompt(positionals, flags, profileOptions, context);
6609
6613
  break;
6610
6614
  case "ab":
6611
- await runPromptAb(flags, profileOptions, context);
6612
- break;
6615
+ return runPromptAb(flags, profileOptions, context);
6613
6616
  case "propose":
6614
6617
  await runPromptPropose(positionals, flags, profileOptions, context);
6615
6618
  break;
@@ -6624,6 +6627,7 @@ async function runPromptsCommand(input, legacyFlags, legacyProfileOptions) {
6624
6627
  default:
6625
6628
  throw new Error(`Unknown prompts command '${subcommand}'. Use init, status, diff, sync, promote, ab, propose, list, show, proposals, usage, replay-runs, or decide.`);
6626
6629
  }
6630
+ return 0;
6627
6631
  }
6628
6632
  async function initPrompts(options = {}) {
6629
6633
  const cwd = process.cwd();
@@ -7284,17 +7288,25 @@ var FIXES_BLOCK_END = "<!-- moda:fixes:end -->";
7284
7288
  function renderFixesBlock() {
7285
7289
  return [
7286
7290
  FIXES_BLOCK_BEGIN,
7287
- "## Moda Fixes (managed block — edits inside are overwritten by moda-cli)",
7291
+ "## Fixing production issues with Moda (managed block — edits inside are overwritten by moda-cli)",
7292
+ "",
7293
+ "Moda supplies the production evidence; you propose and make the fix yourself.",
7288
7294
  "",
7289
- "- Before editing prompt or skill files, run `moda fixes` to see the ranked",
7290
- ' queue of Moda Fixes ("a fix with proof") already drafted for this repo,',
7291
- " and `moda fix <fix_id> --packet` for the evidence packet.",
7292
- "- Gate any prompt/skill change against production evidence with",
7293
- " `moda fix verify <fix_id> [--prompt-file=<path>]`. Exit codes: 0 = holdout",
7294
- " win vs baseline (pass), 1 = failing (per-case findings in the envelope),",
7295
- " 3 = degraded/inconclusive — never treat exit 3 as a pass.",
7296
- "- Fix PRs must carry the magic word `Fixes MODA-FIX-<SHORTREF>` in the PR",
7297
- " body so the merge confirms the fix and starts production monitoring.",
7295
+ "- Find what to fix: `moda investigate` ranks tool failures, user frustrations,",
7296
+ " and top Problems with evidence; `moda problems` ranks cross-signal Problems",
7297
+ " by root cause; `moda failures` lists tool failures only.",
7298
+ "- Read the evidence before editing: `moda problem <problem_id>` (dossier),",
7299
+ " `moda problem <problem_id> --evidence` (attribution rationales and anchors),",
7300
+ " `moda problem <problem_id> --traces` (affected traces),",
7301
+ " `moda tool-failure-detail <tool_name>` (failing calls in context), and",
7302
+ " `moda context <conversation_id>` (the messages around a turn; `--all` for",
7303
+ " the whole trace).",
7304
+ "- Propose the change in the code, prompt, tool definition, or skill that",
7305
+ " causes the issue, and cite the Moda problem or trace ids it is based on",
7306
+ " in the PR description.",
7307
+ "- After the fix ships, record it with",
7308
+ " `moda problem-feedback <problem_id> --action=mark_fixed`; if the issue",
7309
+ " is detected again, the Problem comes back.",
7298
7310
  FIXES_BLOCK_END
7299
7311
  ].join(`
7300
7312
  `);
package/dist/cli.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  runPromptsCommand,
9
9
  runSkillsCommand,
10
10
  runStatusCommand
11
- } from "./cli-141ca3yv.js";
11
+ } from "./cli-j2rdgd3p.js";
12
12
  import {
13
13
  ApiError,
14
14
  HARNESS_REPORT_APPROVAL_PATH,
@@ -6899,7 +6899,7 @@ function buildManifest(commands) {
6899
6899
  exit_codes: [
6900
6900
  { code: 0, name: "ok", meaning: "Command completed successfully." },
6901
6901
  { code: 1, name: "error", meaning: "Command, input, API, network, or unexpected failure." },
6902
- { code: 3, name: "degraded", meaning: "Degraded result: `moda ask` local fallback, `moda fix verify` gate inconclusive/blocked-coverage (never treat as a pass), or `moda fixes drive` timeout with fixes still advancing." },
6902
+ { code: 3, name: "degraded", meaning: "Degraded result: `moda ask` local fallback." },
6903
6903
  { code: 4, name: "auth_required", meaning: "Run login_command, then resume." },
6904
6904
  { code: 5, name: "input_required", meaning: "Choose from input_request choices, then resume." },
6905
6905
  { code: 130, name: "cancelled", meaning: "Interrupted or output consumer closed." }
@@ -6923,7 +6923,7 @@ function buildManifest(commands) {
6923
6923
  "moda.intelligence.v1",
6924
6924
  "production_ask.v0.1"
6925
6925
  ],
6926
- commands: commands.map((command) => ({
6926
+ commands: commands.filter((command) => !command.hidden).map((command) => ({
6927
6927
  name: command.name,
6928
6928
  aliases: command.aliases ?? [],
6929
6929
  summary: command.description,
@@ -6971,8 +6971,6 @@ function event(name, when, terminal, deprecated = false) {
6971
6971
  function exitCodesForCommand(command) {
6972
6972
  if (command === "ask")
6973
6973
  return [0, 1, 3, 4, 5, 130];
6974
- if (command === "fix" || command === "fixes")
6975
- return [0, 1, 3, 4, 130];
6976
6974
  if (command === "init" || command === "harness")
6977
6975
  return [0, 1, 4, 5, 130];
6978
6976
  return [0, 1, 4, 130];
@@ -7203,30 +7201,6 @@ Commands:
7203
7201
  skills list|show|policy List pushed skills, show one, or set --live/--local
7204
7202
  registry push Push prompts, skills, and tools from one JSON manifest
7205
7203
 
7206
- Fixes (a fix with proof):
7207
- fixes Ranked Fix queue (--status=S --limit=N --cursor=TOKEN)
7208
- fixes draft-batch Campaign mode: batch-draft fixes for the top-ranked problems
7209
- (--limit=N, 1-25, default 5 — batches cap at 25: LLM spend guard)
7210
- fixes drive Round-robin one advance per active fix per pass until all rest
7211
- (--status=S narrows the server-side scan window to one advancing
7212
- status, --max-fixes=N 1-10 default 3 fixes per run (rest skipped;
7213
- GATING fixes count toward N; least-recently-driven first),
7214
- --timeout=ms default 2h, --pass-interval=ms default 20s;
7215
- exit 3 when the timeout lapses, fixes were skipped, or still advancing)
7216
- fix <fix_id> One Fix: status + gate result; --packet prints moda.fix_packet.v1
7217
- (tool/skill candidates are also written under .moda/fixes/<ref>/);
7218
- --wait drives a still-running pipeline to rest
7219
- fix start <problem_id> Draft a Fix from a Problem (--type=auto|prompt); --wait drives
7220
- scope -> propose -> gate and prints the packet
7221
- fix verify <fix_id> Re-gate on the frozen holdout; --prompt-file=P gates local content
7222
- (exit 0 pass / 1 fail with per-case findings / 3 degraded-inconclusive)
7223
- Refuses a re-gate within 10 min of the last verdict unless --yes
7224
- fix checkout <fix_id> Write the candidate at its target source path (never runs git)
7225
- fix submit <fix_id> Deliver: --pr opens a draft PR | --local-ref=<branch> records your branch
7226
- fix mark-applied <fix_id> Confirm a candidate you applied in your own stack (--note=TEXT);
7227
- no PR needed — flips to SHIPPED and starts monitoring
7228
- fix dismiss <fix_id> Reject with --reason=TEXT (feeds problem feedback)
7229
-
7230
7204
  Options:
7231
7205
  --help Show this help message
7232
7206
  --version Show version number
@@ -7489,10 +7463,6 @@ Examples:
7489
7463
  moda prompts ab --baseline=prompts/agent.prompt.md --candidate=prompts/agent-v2.prompt.md --traces=conv_1,conv_2
7490
7464
  moda prompts ab --baseline=prompts/agent.prompt.md --candidate=prompts/agent-v2.prompt.md --traces=conv_1@412 # replay from msg 412
7491
7465
  moda skills pull
7492
- moda fixes
7493
- moda fix start <problem_id> --wait
7494
- moda fix verify <fix_id> --prompt-file=prompts/agent.prompt.md
7495
- moda fix mark-applied <fix_id> --note="tool description updated in our agent config"
7496
7466
 
7497
7467
  Run \`moda <command> --help\` for a command's subcommands, and
7498
7468
  \`moda <command> <subcommand> --help\` for that subcommand's flags
@@ -8330,8 +8300,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
8330
8300
  assertHandParsedFlags(command, flags, positionals);
8331
8301
  switch (command) {
8332
8302
  case "prompts": {
8333
- await runPromptsCommand(context);
8334
- break;
8303
+ return runPromptsCommand(context);
8335
8304
  }
8336
8305
  case "overview": {
8337
8306
  const args = flagsToArgs(flags);
@@ -9375,7 +9344,7 @@ var commandRegistry = createCommandRegistry([
9375
9344
  resetApiRequestCountBeforeRun: true,
9376
9345
  telemetry: "result",
9377
9346
  handler: async (context) => {
9378
- const { runInit } = await import("./index-cnfwmzew.js");
9347
+ const { runInit } = await import("./index-nepr7cw7.js");
9379
9348
  if (context.outputMode === "agent-stream") {
9380
9349
  context.output.writeEvent({
9381
9350
  event: "started",
@@ -10204,6 +10173,7 @@ var commandRegistry = createCommandRegistry([
10204
10173
  },
10205
10174
  {
10206
10175
  name: "fixes",
10176
+ hidden: true,
10207
10177
  description: 'List the ranked queue of Fixes ("a fix with proof"); campaign mode batch-drafts and drives them',
10208
10178
  examples: [
10209
10179
  "moda fixes",
@@ -10225,6 +10195,7 @@ var commandRegistry = createCommandRegistry([
10225
10195
  },
10226
10196
  {
10227
10197
  name: "fix",
10198
+ hidden: true,
10228
10199
  description: 'Draft, verify, check out, submit, and dismiss Fixes ("a fix with proof")',
10229
10200
  subcommands: FIX_SUBCOMMAND_HELP,
10230
10201
  examples: [
@@ -3,7 +3,7 @@ import {
3
3
  initPrompts,
4
4
  runPromptSync,
5
5
  runSkillSync
6
- } from "./cli-141ca3yv.js";
6
+ } from "./cli-j2rdgd3p.js";
7
7
  import {
8
8
  codingAgentDisplayName,
9
9
  describeCodingAgentEvent,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moda-ai/cli",
3
- "version": "1.43.1",
3
+ "version": "1.44.0",
4
4
  "description": "CLI for Moda - AI agent analytics and observability",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema_version": "moda.skill_index.v1",
3
- "bundled_at": "2026-10-09T03:57:10.818Z",
4
- "cli_version": "1.43.1",
3
+ "bundled_at": "2026-10-09T08:32:09.674Z",
4
+ "cli_version": "1.44.0",
5
5
  "skills": [
6
6
  {
7
7
  "id": "integration-cloudflare-think",
@@ -900,86 +900,37 @@ rejected, matching what the server accepts. Skill keys are stricter than the
900
900
  server (letters, digits, `_`, `-`) because they double as `.claude/skills/<key>/`
901
901
  directory names.
902
902
 
903
- ### 8. Fixing detected Problems (`moda fix` — a fix with proof)
903
+ ### 8. Fixing detected Problems
904
904
 
905
- Moda turns detected Problems into **Fixes**: a routed candidate change plus a
906
- replay **gate** that proves it on held-out production evidence. Use this loop
907
- whenever you are asked to fix a detected Problem, or before hand-editing
908
- prompt/skill files in a repo that talks to Moda.
909
-
910
- Fixes are typed by where the evidence points: `PROMPT` (a managed prompt
911
- revision — the checkout/verify/submit loop below), `TOOL_SCHEMA` (a proposed
912
- rewrite of one tool's description), and `SKILL` (a drafted SKILL.md for an
913
- agent-behavior problem). Tool and skill candidates are not repo files: read
914
- them from the packet (they are also written locally under
915
- `.moda/fixes/<SHORTREF>/`), apply them in your own stack, then confirm with
916
- `moda fix mark-applied` — no GitHub integration required.
917
-
918
- The fail-to-pass loop:
905
+ Moda does not draft fixes. It supplies the production evidence; you propose
906
+ and make the fix yourself, in the code, prompt, tool definition, or skill that
907
+ causes the issue. Use this loop whenever you are asked to fix a detected
908
+ Problem, or before hand-editing prompt/skill files in a repo that talks to Moda.
919
909
 
920
910
  ```bash
921
- moda fixes # ranked queue of fixes with proof
922
- moda fix <fix_id> --packet # moda.fix_packet.v1: cause, target
923
- # file, evidence links, verify cmd,
924
- # handback + magic word; tool/skill
925
- # candidates land in .moda/fixes/
926
- moda fix start <problem_id> --wait # draft from a Problem and drive
927
- # scope -> propose -> gate
928
- moda fix checkout <fix_id> # PROMPT fixes: write the candidate
929
- # at its target source path
930
- # (NEVER runs git)
931
- # ...edit the target file...
932
- moda fix verify <fix_id> --prompt-file=<path> # re-gate local content on the
933
- # frozen holdout (PROMPT only)
934
- # iterate edit -> verify until exit 0, then hand back:
935
- moda fix submit <fix_id> --pr # draft PR via the Moda GitHub App
936
- moda fix submit <fix_id> --local-ref=<branch> # or record your own branch
937
- moda fix mark-applied <fix_id> --note="…" # tool/skill/no-PR path: confirm a
938
- # candidate you applied yourself
939
- moda fix dismiss <fix_id> --reason="why" # reject (feeds problem feedback)
911
+ moda investigate # rank tool failures, frustrations,
912
+ # and top Problems with evidence
913
+ moda problems # cross-signal Problems by root cause
914
+ moda problem <problem_id> # the dossier: what, where, how often
915
+ moda problem <problem_id> --evidence # attribution rationales and anchors
916
+ moda problem <problem_id> --traces # affected traces with anchors
917
+ moda tool-failure-detail <tool_name> # failing calls with surrounding turns
918
+ moda context <conversation_id> --window=3 # the messages around one turn
919
+ # ...propose and make the change, citing the problem/trace ids in the PR...
920
+ moda problem-feedback <problem_id> --action=mark_fixed # after it ships
940
921
  ```
941
922
 
942
- Every gate replays the holdout, so `moda fix verify` refuses to re-gate a fix
943
- whose last verdict landed less than 10 minutes ago (`gateResult.completedAt`;
944
- verdicts without that stamp have no cooldown) and sends nothing. The error
945
- shows the exact command with `--yes` to gate anyway. Pass `--yes` only when you
946
- changed the candidate since that verdict. `moda fixes drive` advances at most
947
- `--max-fixes` fixes per run (default 3, max 10; fixes already `GATING` count
948
- toward the cap; each run takes the least-recently-driven fixes first), lists the rest in
949
- `data.skipped`, and exits 3 until a re-run has driven them. `moda fixes
950
- draft-batch` drafts 5 fixes unless you pass `--limit` (max 25).
951
-
952
- **`moda fix verify` exit codes are the contract — branch on them:**
923
+ Rules that keep the fix grounded:
953
924
 
954
- | Exit | Meaning | How to treat it |
955
- |---|---|---|
956
- | `0` | gate pass — the candidate beat baseline on the frozen holdout (wins clear the noise floor) | Safe to submit. |
957
- | `1` | gate fail — per-case findings ride the envelope's `findings[]` (`case:<id>` entries with baseline/candidate pass) | Edit the candidate and re-`verify`. |
958
- | `3` | degraded/inconclusive — too many abstentions, blocked coverage, or no verdict | **Never treat as a pass.** Re-verify or read `moda fix <fix_id> --packet`. |
959
-
960
- Rules that keep the proof honest:
961
-
962
- - The verdict reads only **holdout** cases the proposer never saw; repair
963
- rows are training cases, never the headline.
964
- - The gate compares against a noise floor from a baseline-vs-baseline control
965
- run — a "win" inside the noise floor does not pass.
966
- - `checkout` only writes the file. Branching (`moda/fix/<shortref-lower>`),
967
- committing, and pushing are yours; the CLI never runs git.
968
- - Fix PRs end with the magic word `Fixes MODA-FIX-<SHORTREF>` in the body —
969
- Moda-authored PRs carry it automatically; hand-authored PRs must include it
970
- so the merge confirms the fix and starts production monitoring.
971
- - `mark-applied` is the confirmation for changes shipped without a PR (tool
972
- descriptions, installed skills, hand-applied prompts): it flips the fix to
973
- `SHIPPED`, records your `--note`, and starts the same monitoring the merge
974
- webhook would. It is idempotent — repeating it is a duplicate no-op.
975
- - `TOOL_SCHEMA` fixes gate like prompt fixes (both arms pin the same current
976
- prompt; the proposed description is the only delta). `SKILL` fixes rest at
977
- `PROPOSED` until the skill is registered with the Moda skill harness — an
978
- inline drafted SKILL.md cannot enter the gate, so deliver it via the packet
979
- and `mark-applied`.
980
- - The pipeline is advance-on-poll: `--wait` (on `start`, `verify`, or
981
- `moda fix <fix_id> --wait`) drives it; a fix left `GATING` will not finish
982
- on its own.
925
+ - Read the evidence before editing. Base the change on what the traces show,
926
+ not on the Problem's title alone.
927
+ - Cite the Moda problem id and the trace ids you relied on in the PR
928
+ description, so a reviewer can open the same evidence.
929
+ - To test a prompt change against real traffic before shipping it, A/B it with
930
+ `moda prompts ab --baseline=<path> --candidate=<path> --traces=<ids>` (see
931
+ section 7).
932
+ - Mark the Problem fixed only after the change ships. If the issue is detected
933
+ again, the Problem comes back; `moda problem-reopen` reopens it by hand.
983
934
 
984
935
  ### 9. Custom signals and false positives
985
936
 
@@ -1060,7 +1011,7 @@ moda detection-review <problem_id> --conversation-id=<id> \
1060
1011
  ### 10. Everything the dashboard does, from the CLI
1061
1012
 
1062
1013
  Every command below needs only an API key, and the tenant comes from the key.
1063
- Writes listed here accept `--dry-run` (prints the exact request, sends nothing) except `problem-feedback`, `false-positive`, `detection-review`, `signal-label`, `problem-linear-file`, `prompts promote|ab|propose`, and `fix`/`fixes`. Those refuse `--dry-run` before sending anything, so run them only when you mean it.
1014
+ Writes listed here accept `--dry-run` (prints the exact request, sends nothing) except `problem-feedback`, `false-positive`, `detection-review`, `signal-label`, `problem-linear-file`, and `prompts promote|ab|propose`. Those refuse `--dry-run` before sending anything, so run them only when you mean it.
1064
1015
 
1065
1016
  | Dashboard | CLI |
1066
1017
  |---|---|
@@ -1077,7 +1028,6 @@ Writes listed here accept `--dry-run` (prints the exact request, sends nothing)
1077
1028
  | Prompts registry | `moda prompts list [--label --search]`, `show <key>`, `proposals <key>`, `usage <key>`, `replay-runs <key>`, `decide <key> <proposal_id> --action=merge\|reject\|reopen` |
1078
1029
  | Skills library | `moda skills list`, `show <key>`, `policy <key> --live\|--local` |
1079
1030
  | Harness pages | `moda harness list`, `show <id>`, `versions <id>`, `diff <id> --from=… --to=…` |
1080
- | Fixes inbox | `moda fixes`, `moda fix <id>`, `fix start <problem_id>`, `fix dismiss` … |
1081
1031
 
1082
1032
  Not available to API keys on purpose (a human does these in the dashboard):
1083
1033
  members/invites/roles, API-key minting, billing, provider credentials,
@@ -1284,14 +1234,6 @@ npx: `npx -p @moda-ai/cli moda <command>`.
1284
1234
  | `moda prompts list\|show\|proposals\|usage\|replay-runs\|decide` | Read the prompt registry; merge/reject proposals |
1285
1235
  | `moda replays sets\|runs\|run\|playouts\|playout` | Replay results: run history, per-seed verdicts, playout transcripts with tool provenance (read-only) |
1286
1236
  | `moda skills list\|show\|policy` / `moda harness list\|show\|versions\|diff` | Skill library and synced harnesses |
1287
- | `moda fixes` | Ranked queue of Fixes ("a fix with proof"); `--status=S`, `--limit=N`, `--cursor=TOKEN` |
1288
- | `moda fix <fix_id>` | One Fix: status + gate result; `--packet` prints `moda.fix_packet.v1` and writes tool/skill candidates under `.moda/fixes/<ref>/`; `--wait` drives a running pipeline to rest |
1289
- | `moda fix start <problem_id>` | Draft a Fix from a Problem (`--type=auto\|prompt`); `--wait` drives scope → propose → gate |
1290
- | `moda fix verify <fix_id>` | Re-gate on the frozen holdout; `--prompt-file=P` gates local content, PROMPT fixes only (exit `0` pass / `1` fail with per-case findings / `3` degraded — never a pass) |
1291
- | `moda fix checkout <fix_id>` | Write the candidate at its target source path (never runs git; PROMPT fixes only) |
1292
- | `moda fix submit <fix_id>` | Deliver: `--pr` opens a draft PR \| `--local-ref=<branch>` records your branch |
1293
- | `moda fix mark-applied <fix_id>` | Confirm a candidate you applied in your own stack (`--note=TEXT`, ≤600 chars); no PR needed — flips to SHIPPED and starts monitoring |
1294
- | `moda fix dismiss <fix_id>` | Reject with `--reason=TEXT` (feeds problem feedback) |
1295
1237
 
1296
1238
  `moda search` flags: `--mode=keyword|semantic|hybrid` (default `hybrid`),
1297
1239
  `--user-id`, `--time-range=<range>`, `--limit=N` (1–100, default 20).