@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 +71 -0
- package/dist/chunk-OTQQZKPK.js +6 -0
- package/dist/index.js +90 -8
- package/dist/init.js +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-UTST6AEP.js +0 -6
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.
|
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.
|
|
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: "
|
|
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
|
|
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 (
|
|
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
|
|
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
package/dist/version.js
CHANGED
package/package.json
CHANGED