@mushi-mushi/cli 0.15.0 → 0.17.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/README.md CHANGED
@@ -215,6 +215,77 @@ mushi fixes tail --report-id 11111111-2222-3333-4444-555555555555
215
215
  Exits automatically when the job reaches a terminal status (`completed`,
216
216
  `failed`, `cancelled`, `skipped`).
217
217
 
218
+ ### `mushi fixes merge <fixId>`
219
+
220
+ Squash-merge (or merge/rebase) the fix PR on GitHub and run the same post-merge
221
+ bookkeeping as the admin console: `merged_at`, report → **Fixed**, reporter
222
+ notification, `fix.applied` webhooks.
223
+
224
+ ```bash
225
+ mushi fixes merge 75199dde-f726-404a-b5f7-be17bf7a3a46
226
+ mushi fixes merge <fixId> --method squash # default
227
+ mushi fixes merge <fixId> --method merge
228
+ mushi fixes merge <fixId> --method rebase
229
+ mushi fixes merge <fixId> --json
230
+ ```
231
+
232
+ Requires an admin API key with `mcp:write` scope and a connected GitHub App or PAT.
233
+ Draft PRs are auto-readied via GraphQL before merge.
234
+
235
+ ### `mushi fixes refresh-ci <fixId>`
236
+
237
+ Pull the latest GitHub Actions check-run status on demand (same as **Refresh CI
238
+ status** in the console). Useful when webhooks drop or you just pushed to the PR
239
+ branch.
240
+
241
+ ```bash
242
+ mushi fixes refresh-ci <fixId>
243
+ mushi fixes refresh-ci <fixId> --json
244
+ ```
245
+
246
+ ---
247
+
248
+ ## QA coverage & TDD
249
+
250
+ ```bash
251
+ mushi stories map --url https://your-app.com --wait
252
+ mushi tdd gen <storyId> --mode review
253
+ mushi tdd pending
254
+ mushi tdd approve <qaStoryId>
255
+ mushi tdd improve
256
+ mushi qa stories
257
+ mushi qa runs <storyId>
258
+ mushi qa run <storyId>
259
+ mushi qa audit
260
+ ```
261
+
262
+ ---
263
+
264
+ ## Skill pipelines
265
+
266
+ ```bash
267
+ mushi skills list [--category workflow] [--search "fix"]
268
+ mushi skills show workflow-fix-and-ship
269
+ mushi skills sync
270
+
271
+ mushi pipeline start <reportId> --skill workflow-fix-and-ship [--mode cloud|handoff]
272
+ mushi pipeline watch <runId-or-prefix>
273
+ mushi pipeline checkin <runId-or-prefix> --step 0 --status passed
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Integrations & BYOK
279
+
280
+ ```bash
281
+ mushi integrations list
282
+ mushi integrations test slack|sentry|github
283
+ mushi keys list
284
+ MUSHI_BYOK_KEY=sk-ant-... mushi keys add --provider anthropic --label "Backup"
285
+ mushi slack status
286
+ mushi slack test
287
+ ```
288
+
218
289
  ## Security notes
219
290
 
220
291
  - `~/.mushirc` is written with mode `0o600` on Unix. Legacy configs with looser permissions are tightened on load.
@@ -0,0 +1,6 @@
1
+ // src/version.ts
2
+ var MUSHI_CLI_VERSION = true ? "0.17.0" : "0.0.0-dev";
3
+
4
+ export {
5
+ MUSHI_CLI_VERSION
6
+ };
package/dist/index.js CHANGED
@@ -598,7 +598,7 @@ function getFrameworkFromPkg(pkg) {
598
598
  }
599
599
 
600
600
  // src/version.ts
601
- var MUSHI_CLI_VERSION = true ? "0.15.0" : "0.0.0-dev";
601
+ var MUSHI_CLI_VERSION = true ? "0.17.0" : "0.0.0-dev";
602
602
 
603
603
  // src/init.ts
604
604
  var ENV_FILES = [".env.local", ".env"];
@@ -2441,7 +2441,7 @@ reports.command("resolve <id>").description("Mark a report as resolved (shorthan
2441
2441
  });
2442
2442
  reports.command("reopen <id>").description("Reopen a resolved or dismissed report").option("--note <text>", "Note explaining the reopen").option("--json", "Machine-readable JSON output").action(async (id, opts) => {
2443
2443
  const config = requireConfig();
2444
- const body = { status: "new" };
2444
+ const body = { status: "reopened" };
2445
2445
  if (opts.note) body["note"] = opts.note;
2446
2446
  const result = await apiCall(`/v1/sync/reports/${id}`, config, {
2447
2447
  method: "PATCH",
@@ -2461,6 +2461,18 @@ reports.command("reopen <id>").description("Reopen a resolved or dismissed repor
2461
2461
  console.log(`\u2713 Reopened report ${id}`);
2462
2462
  }
2463
2463
  });
2464
+ reports.command("verify <id>").description("Mark a fixed report as verified by the reporter (operator shortcut)").option("--note <text>", "Optional audit note").option("--json", "Machine-readable JSON output").action(async (id, opts) => {
2465
+ const config = requireConfig();
2466
+ const body = { status: "verified" };
2467
+ if (opts.note) body["note"] = opts.note;
2468
+ const result = await apiCall(`/v1/sync/reports/${id}`, config, {
2469
+ method: "PATCH",
2470
+ body: JSON.stringify(body)
2471
+ });
2472
+ if (!result.ok) die(result);
2473
+ if (opts.json) console.log(JSON.stringify(result.data, null, 2));
2474
+ else console.log(`\u2713 Verified report ${id}`);
2475
+ });
2464
2476
  reports.command("dismiss <id>").description("Dismiss a report (not a real bug / out of scope)").option("--note <text>", "Reason for dismissal").option("--json", "Machine-readable JSON output").action(async (id, opts) => {
2465
2477
  const config = requireConfig();
2466
2478
  const body = { status: "dismissed" };
@@ -3302,6 +3314,79 @@ fixes.command("tail").description(
3302
3314
  }
3303
3315
  }
3304
3316
  });
3317
+ fixes.command("merge <fixId>").description(
3318
+ "Squash-merge the fix PR on GitHub and mark the report Fixed (same as console merge)"
3319
+ ).option(
3320
+ "--method <method>",
3321
+ "GitHub merge method: squash (default), merge, or rebase",
3322
+ "squash"
3323
+ ).option("--json", "Machine-readable JSON output").action(async (fixId, opts) => {
3324
+ const config = loadConfig();
3325
+ if (!config.apiKey) {
3326
+ console.error("Run `mushi login` first");
3327
+ process.exit(1);
3328
+ }
3329
+ if (!config.endpoint) {
3330
+ console.error("No endpoint configured. Run `mushi init`");
3331
+ process.exit(1);
3332
+ }
3333
+ const method = opts.method;
3334
+ if (!["squash", "merge", "rebase"].includes(method)) {
3335
+ console.error("--method must be squash, merge, or rebase");
3336
+ process.exit(1);
3337
+ }
3338
+ const result = await apiCall(`/v1/admin/fixes/${fixId}/merge`, config, {
3339
+ method: "POST",
3340
+ body: JSON.stringify({ mergeMethod: method })
3341
+ });
3342
+ if (!result.ok) {
3343
+ if (opts.json) {
3344
+ console.log(JSON.stringify({ ok: false, error: result.error }, null, 2));
3345
+ } else {
3346
+ console.error("Merge failed:", result.error.message);
3347
+ }
3348
+ process.exit(1);
3349
+ }
3350
+ const data = result.data ?? {};
3351
+ if (opts.json) {
3352
+ console.log(JSON.stringify({ ok: true, ...data }, null, 2));
3353
+ return;
3354
+ }
3355
+ if (data.alreadyMerged) {
3356
+ console.log(`PR was already merged. Report status: ${data.reportStatus ?? "unknown"}`);
3357
+ } else {
3358
+ console.log(`Merged successfully. Report status: ${data.reportStatus ?? "fixed"}`);
3359
+ }
3360
+ });
3361
+ fixes.command("refresh-ci <fixId>").description("Pull latest GitHub Actions check-run status for a fix attempt (on-demand ci-sync)").option("--json", "Machine-readable JSON output").action(async (fixId, opts) => {
3362
+ const config = loadConfig();
3363
+ if (!config.apiKey) {
3364
+ console.error("Run `mushi login` first");
3365
+ process.exit(1);
3366
+ }
3367
+ if (!config.endpoint) {
3368
+ console.error("No endpoint configured. Run `mushi init`");
3369
+ process.exit(1);
3370
+ }
3371
+ const result = await apiCall(`/v1/admin/fixes/${fixId}/refresh-ci`, config, { method: "POST" });
3372
+ if (!result.ok) {
3373
+ if (opts.json) {
3374
+ console.log(JSON.stringify({ ok: false, error: result.error }, null, 2));
3375
+ } else {
3376
+ console.error("CI refresh failed:", result.error.message);
3377
+ }
3378
+ process.exit(1);
3379
+ }
3380
+ const data = result.data ?? {};
3381
+ if (opts.json) {
3382
+ console.log(JSON.stringify({ ok: true, ...data }, null, 2));
3383
+ return;
3384
+ }
3385
+ const status = data.check_run_status ?? "unknown";
3386
+ const conclusion = data.check_run_conclusion ?? "\u2014";
3387
+ const updated = data.check_run_updated_at ? new Date(data.check_run_updated_at).toISOString() : "\u2014";
3388
+ console.log(`CI status: ${status} \xB7 conclusion: ${conclusion} \xB7 updated: ${updated}`);
3389
+ });
3305
3390
  var stories = program.command("stories").description("TDD story mapping and test generation");
3306
3391
  stories.command("map").description("Crawl a live app URL and automatically discover user stories (writes inventory proposal)").requiredOption("--url <url>", "Live app URL to crawl (e.g. https://your-app.vercel.app)").option("--max-pages <n>", "Max pages to crawl", "20").option("--provider <p>", "Crawl provider: firecrawl (default) or browserbase", "firecrawl").option("--cursor-refine", "Open a Cursor Cloud PR to refine the draft against repo code").option("--wait", "Wait for the crawl to complete and print results").action(async (opts) => {
3307
3392
  const config = loadConfig();
@@ -3734,7 +3819,7 @@ Recent runs for story ${storyId.slice(0, 8)}\u2026:
3734
3819
  const consoleUrl = config.consoleUrl ?? "https://app.mushi.ai";
3735
3820
  console.log(`
3736
3821
  Open in console: ${consoleUrl}/qa-coverage?story=${storyId}`);
3737
- console.log(` Tip: run 'mushi config consoleUrl http://localhost:6464' to set your local console URL`);
3822
+ console.log(` Tip: run 'mushi config consoleUrl <url>' to override (e.g. http://localhost:6464 for local dev)`);
3738
3823
  console.log();
3739
3824
  });
3740
3825
  qa.command("run <storyId>").description("Manually trigger a QA story run (fire-and-forget; check results with `mushi qa runs <id>`)").option("--json", "Machine-readable output").action(async (storyId, opts) => {
@@ -3809,14 +3894,11 @@ Examples:
3809
3894
  "Content-Type": "application/json",
3810
3895
  "X-Mushi-Project-Id": projectId
3811
3896
  };
3812
- const jwt = config.jwt ?? null;
3813
3897
  const apiKey = config.apiKey ?? null;
3814
- if (jwt) {
3815
- headers["Authorization"] = `Bearer ${jwt.replace(/[\r\n\0]/g, "")}`;
3816
- } else if (apiKey) {
3898
+ if (apiKey) {
3817
3899
  headers["X-Mushi-Api-Key"] = sanitizeApiKey(apiKey);
3818
3900
  } else {
3819
- process.stderr.write("error: no credentials found. Run `mushi login` first.\n");
3901
+ process.stderr.write("error: no API key found. Run `mushi login` or set MUSHI_API_KEY.\n");
3820
3902
  process.exit(1);
3821
3903
  }
3822
3904
  if (!opts.json) process.stdout.write("Running full-stack audit\u2026 ");
package/dist/init.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-NYPX5KXR.js";
9
9
  import {
10
10
  MUSHI_CLI_VERSION
11
- } from "./chunk-UTST6AEP.js";
11
+ } from "./chunk-OTQQZKPK.js";
12
12
 
13
13
  // src/init.ts
14
14
  import * as p from "@clack/prompts";
package/dist/version.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MUSHI_CLI_VERSION
3
- } from "./chunk-UTST6AEP.js";
3
+ } from "./chunk-OTQQZKPK.js";
4
4
  export {
5
5
  MUSHI_CLI_VERSION
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mushi-mushi/cli",
3
- "version": "0.15.0",
3
+ "version": "0.17.0",
4
4
  "license": "MIT",
5
5
  "description": "CLI for Mushi Mushi — `mushi init` wizard installs the right SDK for your framework, plus report triage and pipeline health commands",
6
6
  "bin": {
@@ -1,6 +0,0 @@
1
- // src/version.ts
2
- var MUSHI_CLI_VERSION = true ? "0.15.0" : "0.0.0-dev";
3
-
4
- export {
5
- MUSHI_CLI_VERSION
6
- };