@mushi-mushi/cli 0.29.0 → 0.29.2

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
@@ -445,4 +445,4 @@ The CLI is also importable for tooling (used by `create-mushi-mushi`):
445
445
  MIT
446
446
 
447
447
  <!-- mushi-readme-stats-footer -->
448
- <sub>Monorepo scale (July 2026): 64 edge functions · 410 SQL migrations · 13 outbound plugins · 11 inbound adapters · 19 pipeline agents. Canonical counts: <a href="https://github.com/kensaurus/mushi-mushi/blob/master/docs/stats.md">docs/stats.md</a> · <code>pnpm docs-stats</code></sub>
448
+ <sub>Monorepo scale (July 2026): 64 edge functions · 413 SQL migrations · 13 outbound plugins · 11 inbound adapters · 19 pipeline agents. Canonical counts: <a href="https://github.com/kensaurus/mushi-mushi/blob/master/docs/stats.md">docs/stats.md</a> · <code>pnpm docs-stats</code></sub>
@@ -0,0 +1,8 @@
1
+ // src/version.ts
2
+ var MUSHI_CLI_VERSION = true ? "0.29.2" : "0.0.0-dev";
3
+ var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.24.2";
4
+
5
+ export {
6
+ MUSHI_CLI_VERSION,
7
+ MUSHI_MCP_PIN_SPEC
8
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MUSHI_CLI_VERSION
3
- } from "./chunk-UZZUGLI2.js";
3
+ } from "./chunk-4H5TRTM3.js";
4
4
  import {
5
5
  assertEndpoint,
6
6
  normalizeEndpoint
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  MUSHI_CLI_VERSION,
4
4
  MUSHI_MCP_PIN_SPEC
5
- } from "./chunk-F4EGZNKA.js";
5
+ } from "./chunk-MKUU3GHS.js";
6
6
  import {
7
7
  detectFramework,
8
8
  envVarsToWrite,
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/version.ts
4
+ var MUSHI_CLI_VERSION = true ? "0.29.2" : "0.0.0-dev";
5
+ var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.24.2";
6
+
7
+ export {
8
+ MUSHI_CLI_VERSION,
9
+ MUSHI_MCP_PIN_SPEC
10
+ };
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  resolveSdkEnvKey,
4
4
  runConnect
5
- } from "./chunk-O7PLRNM2.js";
6
- import "./chunk-F4EGZNKA.js";
5
+ } from "./chunk-KZW4X6WB.js";
6
+ import "./chunk-MKUU3GHS.js";
7
7
  import "./chunk-KOBEOGNF.js";
8
8
  import "./chunk-LDPFTQLE.js";
9
9
  import "./chunk-PDX44BCA.js";
@@ -6,10 +6,10 @@ import {
6
6
  saveConfig,
7
7
  savedSdkKeyFor,
8
8
  waitForIngestReady
9
- } from "./chunk-FDDSGZSC.js";
9
+ } from "./chunk-HNLTFQ4N.js";
10
10
  import {
11
11
  MUSHI_MCP_PIN_SPEC
12
- } from "./chunk-UZZUGLI2.js";
12
+ } from "./chunk-4H5TRTM3.js";
13
13
  import {
14
14
  detectFramework,
15
15
  envVarsToWrite,
package/dist/index.js CHANGED
@@ -53,11 +53,11 @@ import {
53
53
  setGlobalOutputFormat,
54
54
  trySaveKeyToKeychain,
55
55
  writeMcpServerEntry
56
- } from "./chunk-O7PLRNM2.js";
56
+ } from "./chunk-KZW4X6WB.js";
57
57
  import {
58
58
  MUSHI_CLI_VERSION,
59
59
  MUSHI_MCP_PIN_SPEC
60
- } from "./chunk-F4EGZNKA.js";
60
+ } from "./chunk-MKUU3GHS.js";
61
61
  import {
62
62
  FRAMEWORKS,
63
63
  detectFramework,
@@ -1512,7 +1512,7 @@ async function checkOnboardingStatus(config, _consoleBase, cwd, doFetch = global
1512
1512
  }
1513
1513
  async function checkVersionDrift(cwd, doFetch) {
1514
1514
  const checks = [];
1515
- const { MUSHI_CLI_VERSION: MUSHI_CLI_VERSION2 } = await import("./version-WHAZE7TY.js");
1515
+ const { MUSHI_CLI_VERSION: MUSHI_CLI_VERSION2 } = await import("./version-QRFWGGZY.js");
1516
1516
  if (MUSHI_CLI_VERSION2 === "0.0.0-dev") return checks;
1517
1517
  const parse2 = (v) => {
1518
1518
  const m = v.replace(/^[~^]/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
@@ -2436,7 +2436,7 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
2436
2436
  if (p.isCancel(answer) || !answer) return;
2437
2437
  const endpoint = resolveCloudEndpoint(options.endpoint);
2438
2438
  try {
2439
- const { runConnect: runConnect2 } = await import("./connect-TGIJLXAN.js");
2439
+ const { runConnect: runConnect2 } = await import("./connect-NCBKOV6O.js");
2440
2440
  const saved = loadConfig();
2441
2441
  const result = await runConnect2(
2442
2442
  {
@@ -4258,6 +4258,41 @@ Note: ${configRelPath} contains your Mushi API key.`);
4258
4258
  }
4259
4259
 
4260
4260
  // src/commands/fix.ts
4261
+ function githubOwnerName(url) {
4262
+ const cleaned = url.trim().replace(/^git@github\.com:/i, "https://github.com/").replace(/\/+$/, "").replace(/\.git$/i, "");
4263
+ const match = cleaned.match(/github\.com\/([^/]+)\/([^/]+)/i);
4264
+ return match ? `${match[1]}/${match[2]}`.toLowerCase() : null;
4265
+ }
4266
+ async function resolveTargetRepoId(repo, cfg) {
4267
+ if (!repo.includes("/")) return requireUuid(repo, "--repo");
4268
+ if (!/^[\w.-]+\/[\w.-]+$/.test(repo)) {
4269
+ throw new MushiCliError("E_INVALID_INPUT", "--repo must be a repo id or owner/name", "e.g. --repo acme/app-backend");
4270
+ }
4271
+ if (!cfg.projectId) {
4272
+ throw new MushiCliError(
4273
+ "E_INVALID_INPUT",
4274
+ "--repo owner/name needs a project to look the repo up in",
4275
+ "pass --project-id or set MUSHI_PROJECT_ID, or pass the repo id instead"
4276
+ );
4277
+ }
4278
+ const res = await apiCall(
4279
+ `/v1/admin/repo/repos?project_id=${encodeURIComponent(cfg.projectId)}`,
4280
+ cfg
4281
+ );
4282
+ if (!res.ok) {
4283
+ console.error("Error listing linked repos:", res.error.message);
4284
+ process.exit(1);
4285
+ }
4286
+ const linked = res.data ?? [];
4287
+ const matches = linked.filter((r) => githubOwnerName(r.repo_url) === repo.toLowerCase());
4288
+ if (matches.length === 1) return matches[0].id;
4289
+ const names = linked.map((r) => githubOwnerName(r.repo_url) ?? r.repo_url).join(", ") || "none";
4290
+ throw new MushiCliError(
4291
+ "E_INVALID_INPUT",
4292
+ matches.length === 0 ? `${repo} is not linked to this project` : `${repo} matches ${matches.length} linked repos; pass the repo id`,
4293
+ `linked repos: ${names}`
4294
+ );
4295
+ }
4261
4296
  function registerFixCommands(program2) {
4262
4297
  const fixCmd = program2.command("fix").description("Dispatch an agentic fix for a report");
4263
4298
  fixCmd.argument("<reportId>", "Report UUID to fix").option(
@@ -4273,12 +4308,18 @@ function registerFixCommands(program2) {
4273
4308
  ).option(
4274
4309
  "--wait",
4275
4310
  "Poll until terminal state and exit non-zero on error/cancelled (CI-friendly)"
4311
+ ).option(
4312
+ "--repo <repoId|owner/name>",
4313
+ "Linked repo to open the fix PR against (a project with several repos). Default: the project's primary repo"
4276
4314
  ).option("-e, --endpoint <url>", "API endpoint (overrides MUSHI_API_ENDPOINT)").option("--api-key <key>", "API key (overrides MUSHI_API_KEY)").option("--project-id <id>", "Project ID (overrides MUSHI_PROJECT_ID)").addHelpText("after", `
4277
4315
  Examples:
4278
4316
  mushi fix abc123 --agent cursor_cloud --wait
4279
4317
  mushi fix abc123 --agent cursor_cloud --model composer-latest --no-auto-pr
4280
4318
  mushi fix abc123 --agent claude_code
4281
4319
 
4320
+ # A project with a frontend and a backend repo: send the fix to the backend
4321
+ mushi fix abc123 --repo acme/app-backend
4322
+
4282
4323
  # CI: fail the pipeline if the fix errors
4283
4324
  mushi fix $REPORT_ID --agent cursor_cloud --wait && echo "Fix PR opened"`).action(async (reportId, opts) => {
4284
4325
  requireUuid(reportId, "reportId");
@@ -4286,6 +4327,7 @@ Examples:
4286
4327
  if (opts.endpoint) cfg.endpoint = opts.endpoint;
4287
4328
  if (opts.apiKey) cfg.apiKey = opts.apiKey;
4288
4329
  if (opts.projectId) cfg.projectId = opts.projectId;
4330
+ const targetRepoId = opts.repo ? await resolveTargetRepoId(opts.repo, cfg) : void 0;
4289
4331
  const isTTY = process.stdout.isTTY;
4290
4332
  const emitEvent = (type, data) => {
4291
4333
  if (isTTY) {
@@ -4295,11 +4337,17 @@ Examples:
4295
4337
  process.stdout.write(JSON.stringify({ type, ...data }) + "\n");
4296
4338
  }
4297
4339
  };
4298
- emitEvent("dispatch.start", { reportId, agent: opts.agent, model: opts.model ?? null });
4340
+ emitEvent("dispatch.start", {
4341
+ reportId,
4342
+ agent: opts.agent,
4343
+ model: opts.model ?? null,
4344
+ targetRepoId: targetRepoId ?? null
4345
+ });
4299
4346
  const body = {
4300
4347
  reportId,
4301
4348
  projectId: cfg.projectId,
4302
- agent: opts.agent
4349
+ agent: opts.agent,
4350
+ ...targetRepoId ? { targetRepoId } : {}
4303
4351
  };
4304
4352
  if (opts.agent === "cursor_cloud") {
4305
4353
  if (opts.model) body.cursorModel = opts.model;
@@ -4314,13 +4362,13 @@ Examples:
4314
4362
  console.error("Error dispatching fix:", result.error.message);
4315
4363
  process.exit(1);
4316
4364
  }
4317
- const { fixId, status, agentId, runId, prUrl } = result.data;
4318
- emitEvent("dispatch.ok", { fixId, status, agentId, runId, prUrl });
4365
+ const { dispatchId, fixId, status, agentId, runId, prUrl } = result.data;
4366
+ emitEvent("dispatch.ok", { dispatchId, fixId, status, agentId, runId, prUrl });
4319
4367
  if (!opts.wait) {
4320
4368
  process.exit(0);
4321
4369
  }
4322
- if (!fixId) {
4323
- console.error("No fixId returned \u2014 cannot poll.");
4370
+ if (!dispatchId) {
4371
+ console.error("No dispatchId returned \u2014 cannot poll.");
4324
4372
  process.exit(1);
4325
4373
  }
4326
4374
  const POLL_MS = 5e3;
@@ -4329,7 +4377,7 @@ Examples:
4329
4377
  for (let i = 0; i < MAX_POLLS; i++) {
4330
4378
  await new Promise((r) => setTimeout(r, POLL_MS));
4331
4379
  const pollResult = await apiCall(
4332
- `/v1/admin/fixes/${fixId}`,
4380
+ `/v1/admin/fixes/dispatch/${dispatchId}`,
4333
4381
  cfg
4334
4382
  );
4335
4383
  if (!pollResult.ok) {
@@ -5335,7 +5383,7 @@ function registerKeysCommands(program2) {
5335
5383
  }
5336
5384
  );
5337
5385
  });
5338
- keys.command("add").description("Add a new API key to the pool").requiredOption("--provider <p>", "Provider: anthropic, openai, firecrawl, browserbase, cursor").option(
5386
+ keys.command("add").description("Add a new API key to the pool").requiredOption("--provider <p>", "Provider: anthropic, openai, firecrawl, browserbase, cursor, supabase").option(
5339
5387
  "--key <k>",
5340
5388
  "The API key value (prefer the MUSHI_BYOK_KEY env var to keep it out of shell history)"
5341
5389
  ).option("--label <l>", "Human-readable label").option("--priority <n>", "Priority (lower = higher priority)", "100").option("--base-url <url>", "Allow-listed OpenAI-compatible HTTPS base URL").action(
@@ -5799,7 +5847,7 @@ function registerAuditCommands(program2) {
5799
5847
  const audit = program2.command("audit").description("Run a full-stack health audit for the current project").option("--json", "Machine-readable JSON output").option("--project-id <id>", "Project ID to audit (defaults to MUSHI_PROJECT_ID from config)").addHelpText("after", `
5800
5848
  Description:
5801
5849
  Fans out to the Mushi backend to run a full-stack health audit:
5802
- \u2022 DB schema + Supabase advisors (requires Supabase PAT in API Keys)
5850
+ \u2022 DB schema + Supabase advisors (requires a linked Supabase project)
5803
5851
  \u2022 Recent backend error logs
5804
5852
  \u2022 Tables without RLS enabled
5805
5853
  \u2022 Gate results: API contract (G3), spec drift (G6), orphan endpoints (G7),
@@ -5808,8 +5856,9 @@ Description:
5808
5856
  Returns a human-readable summary with severity-ranked findings.
5809
5857
 
5810
5858
  Prerequisites:
5811
- 1. Add your Supabase PAT in Admin \u2192 Settings \u2192 API Keys
5812
- 2. Set supabase_project_ref in Admin \u2192 Settings \u2192 Project.
5859
+ 1. Set the Supabase project ref in Admin \u2192 Settings \u2192 General \u2192 Supabase project.
5860
+ 2. Add a scoped, read-only Supabase access token (one project; Database,
5861
+ Edge Functions, Advisors and Logs at Read) in Admin \u2192 Settings \u2192 AI keys \u2192 Supabase.
5813
5862
 
5814
5863
  Examples:
5815
5864
  mushi audit
@@ -8636,23 +8685,131 @@ function gitDefaultBranch(root) {
8636
8685
  }
8637
8686
  return "main";
8638
8687
  }
8688
+ var ENV_EXAMPLES = [".env.example", ".env.local.example", ".env.sample", ".env.template"];
8689
+ var ROOT_APP_DIRS = ["app", "src", "components", "features", "lib", "hooks", "pages"];
8690
+ var MAX_LITERAL_GLOBS = 30;
8691
+ var MAX_READ_BYTES = 512 * 1024;
8692
+ var MAX_SCRIPT_FILES = 400;
8693
+ var DEPLOY_STEPS = [
8694
+ /upload-google-play/i,
8695
+ /upload-testflight/i,
8696
+ /\baltool\b/i,
8697
+ /app-store-connect/i,
8698
+ /\baws\s+s3\s+sync\b/i,
8699
+ /\bwrangler\s+(pages\s+)?deploy\b/i,
8700
+ /cloudflare\/wrangler-action/i,
8701
+ /\bvercel\s+(deploy|--prod)\b/i,
8702
+ /\bsupabase\s+functions\s+deploy\b/i,
8703
+ /\bcapgo\b/i,
8704
+ /\beas\s+update\b/i,
8705
+ /\b(npm|pnpm|yarn)\s+publish\b/i,
8706
+ /\bchangeset\s+publish\b/i
8707
+ ];
8708
+ var WRITES_FILE = /\b(writeFileSync|writeFile|createWriteStream|outputFileSync|outputFile|outputJsonSync|outputJson|writeJsonSync|writeJson|writeTextFile|write_text)\b/;
8709
+ function readCapped(root, path) {
8710
+ const f = readTextFileCapped(join6(root, path), MAX_READ_BYTES);
8711
+ return f.kind === "file" ? f.text : null;
8712
+ }
8713
+ function workspacePatterns(root, pkg) {
8714
+ const out = [];
8715
+ const ws = pkg?.workspaces;
8716
+ const list = Array.isArray(ws) ? ws : isObject2(ws) && Array.isArray(ws.packages) ? ws.packages : [];
8717
+ for (const p3 of list) if (typeof p3 === "string") out.push(p3);
8718
+ const yaml = readCapped(root, "pnpm-workspace.yaml");
8719
+ if (yaml) {
8720
+ let inPackages = false;
8721
+ for (const line of yaml.split(/\r?\n/)) {
8722
+ if (/^packages\s*:/.test(line)) {
8723
+ inPackages = true;
8724
+ continue;
8725
+ }
8726
+ if (/^\S/.test(line)) inPackages = false;
8727
+ const item = inPackages ? /^\s+-\s*["']?([^"'#]+?)["']?\s*(#.*)?$/.exec(line) : null;
8728
+ if (item) out.push(item[1]);
8729
+ }
8730
+ }
8731
+ return out.map((p3) => p3.trim().replace(/^\.\//, "").replace(/\/+$/, "")).filter(Boolean);
8732
+ }
8733
+ function scriptRunner(files) {
8734
+ if (files.has("pnpm-lock.yaml")) return "pnpm";
8735
+ if (files.has("yarn.lock")) return "yarn";
8736
+ if (files.has("bun.lockb") || files.has("bun.lock")) return "bun run";
8737
+ return "npm run";
8738
+ }
8739
+ function tokenOrigin(tokenPath, scripts, scriptFiles, runner) {
8740
+ const isCheck = (name, cmd) => /(^|\s)--check(\s|=|$)/.test(cmd) || /(^|:)check$/.test(name);
8741
+ const namesToken = (file) => {
8742
+ if (file.text.includes(tokenPath)) return true;
8743
+ const pkgDir = file.path.includes("/scripts/") ? file.path.slice(0, file.path.indexOf("/scripts/")) : "";
8744
+ return pkgDir !== "" && tokenPath.startsWith(`${pkgDir}/`) && file.text.includes(tokenPath.slice(pkgDir.length + 1));
8745
+ };
8746
+ const mentioning = scriptFiles.filter(namesToken);
8747
+ const writers = mentioning.filter((f) => WRITES_FILE.test(f.text));
8748
+ const runs = (cmd, file) => cmd.includes(file);
8749
+ let generator;
8750
+ let generated = false;
8751
+ for (const [name, cmd] of scripts) {
8752
+ if (isCheck(name, cmd)) continue;
8753
+ if (cmd.includes(tokenPath) || writers.some((w) => runs(cmd, w.path))) {
8754
+ generated = true;
8755
+ generator ??= `${runner} ${name}`;
8756
+ }
8757
+ }
8758
+ if (writers.length) {
8759
+ generated = true;
8760
+ if (!generator) {
8761
+ const w = writers[0].path;
8762
+ generator = /\.(m?js|cjs)$/.test(w) ? `node ${w}` : w;
8763
+ }
8764
+ }
8765
+ const checked = scripts.some(([name, cmd]) => isCheck(name, cmd) && (cmd.includes(tokenPath) || mentioning.some((f) => runs(cmd, f.path))));
8766
+ if (!generated && !checked) return { role: "source" };
8767
+ return generator && generator.length <= 200 ? { role: "export", generator } : { role: "export" };
8768
+ }
8639
8769
  function starterManifest(root) {
8640
- const files = walk(root, 5e3);
8770
+ const tracked = listRepoFiles2(root).map((e) => e.path);
8771
+ const files = tracked.length ? tracked : walk(root);
8772
+ const fileSet = new Set(files);
8641
8773
  const pkg = readJson(join6(root, "package.json"));
8642
8774
  const deps = { ...pkg?.dependencies ?? {}, ...pkg?.devDependencies ?? {} };
8775
+ const rootScripts = Object.entries(pkg?.scripts ?? {}).filter((e) => typeof e[1] === "string");
8643
8776
  const native = files.some((f) => /^capacitor\.config\.(ts|js|json)$/.test(f)) || "expo" in deps || "react-native" in deps || files.some((f) => f.startsWith("android/") || f.startsWith("ios/"));
8644
8777
  const platforms = ["web", ...files.some((f) => f.startsWith("android/")) || "expo" in deps ? ["android"] : [], ...files.some((f) => f.startsWith("ios/")) || "expo" in deps ? ["ios"] : []];
8645
- const tokens = files.filter((f) => !FIXTURE_DIR.test(f) && (/\.tokens\.json$/.test(f) || /(^|\/)dtcg\/[^/]+\.json$/.test(f))).slice(0, 20);
8778
+ const archived = files.filter((f) => f.endsWith("/ARCHIVED.md")).map((f) => f.slice(0, -"/ARCHIVED.md".length));
8779
+ const isArchived = (f) => archived.some((d) => f.startsWith(`${d}/`));
8780
+ const live = (f) => !FIXTURE_DIR.test(f) && !isArchived(f);
8781
+ const tokenPaths = files.filter((f) => live(f) && (/\.tokens\.json$/.test(f) || /(^|\/)dtcg\/[^/]+\.json$/.test(f))).slice(0, 20);
8646
8782
  const workflows = files.filter((f) => /^\.github\/workflows\/[^/]+\.ya?ml$/.test(f));
8647
- const sourceRoots = [...new Set(files.filter((f) => !FIXTURE_DIR.test(f) && /^(apps|packages)\/[^/]+\/src\/.+\.(tsx|css)$/.test(f)).map((f) => f.split("/").slice(0, 3).join("/")))].slice(0, 12);
8648
- const literalGlobs = sourceRoots.length ? sourceRoots.map((r) => `${r}/**/*.{ts,tsx,css}`) : ["src/**/*.{ts,tsx,css}", "app/**/*.{ts,tsx,css}"];
8649
- const migrationsDir = files.find((f) => !FIXTURE_DIR.test(f) && /(^|\/)supabase\/migrations\/[^/]+\.sql$/.test(f))?.replace(/\/[^/]+$/, "");
8783
+ const hasSource = (dir, ext) => files.some((f) => f.startsWith(`${dir}/`) && live(f) && ext.test(f));
8784
+ const rootIsApp = files.some((f) => /^(next|vite)\.config\.(js|mjs|cjs|ts|mts)$/.test(f)) || "expo" in deps || rootScripts.some(([name]) => name === "dev" || name === "build");
8785
+ const rootDirs = rootIsApp ? ROOT_APP_DIRS.filter((d) => hasSource(d, /\.(ts|tsx|css)$/)) : [];
8786
+ const patterns = workspacePatterns(root, pkg);
8787
+ let packageRoots;
8788
+ if (patterns.length) {
8789
+ const include = patterns.filter((p3) => !p3.startsWith("!"));
8790
+ const exclude = patterns.filter((p3) => p3.startsWith("!")).map((p3) => p3.slice(1));
8791
+ const pkgDirs = [...new Set(files.filter((f) => f.endsWith("/package.json") && !f.includes("node_modules/")).map((f) => f.slice(0, -"/package.json".length)))];
8792
+ packageRoots = pkgDirs.filter((d) => !isArchived(`${d}/`) && include.some((p3) => matchGlob(d, p3)) && !exclude.some((p3) => matchGlob(d, p3))).sort().flatMap((d) => hasSource(`${d}/src`, /\.(tsx|css)$/) ? [`${d}/src`] : hasSource(d, /\.(tsx|css)$/) ? [d] : []);
8793
+ } else {
8794
+ packageRoots = [...new Set(files.filter((f) => live(f) && /^(apps|packages)\/[^/]+\/src\/.+\.(tsx|css)$/.test(f)).map((f) => f.split("/").slice(0, 3).join("/")))];
8795
+ }
8796
+ const scanRoots = [.../* @__PURE__ */ new Set([...rootDirs, ...packageRoots])].slice(0, MAX_LITERAL_GLOBS);
8797
+ const literalGlobs = scanRoots.length ? scanRoots.map((r) => `${r}/**/*.{ts,tsx,css}`) : ["src/**/*.{ts,tsx,css}", "app/**/*.{ts,tsx,css}"];
8798
+ const migrationsDir = files.find((f) => live(f) && /(^|\/)supabase\/migrations\/[^/]+\.sql$/.test(f))?.replace(/\/[^/]+$/, "");
8799
+ const tokens = tokenPaths.length ? (() => {
8800
+ const scriptFiles = files.filter((f) => live(f) && !f.includes("node_modules/") && /(^|\/)scripts\/.+\.(m?[jt]s|c[jt]s|py|sh)$/.test(f)).slice(0, MAX_SCRIPT_FILES).flatMap((path) => {
8801
+ const text2 = readCapped(root, path);
8802
+ return text2 === null ? [] : [{ path, text: text2 }];
8803
+ });
8804
+ const runner = scriptRunner(fileSet);
8805
+ return tokenPaths.map((path) => ({ path, ...tokenOrigin(path, rootScripts, scriptFiles, runner), format: "dtcg-2025.10" }));
8806
+ })() : [];
8650
8807
  const manifest = {
8651
8808
  version: 1,
8652
8809
  app: { name: pkg?.name ?? root.split(/[\\/]/).pop(), kind: native ? "app" : "site", platforms }
8653
8810
  };
8654
8811
  if (tokens.length) {
8655
- manifest.design = { tokens: tokens.map((path) => ({ path, role: "source", format: "dtcg-2025.10" })), literalScan: { globs: literalGlobs, ignore: ["**/*.test.*"] } };
8812
+ manifest.design = { tokens, literalScan: { globs: literalGlobs, ignore: ["**/*.test.*"] } };
8656
8813
  }
8657
8814
  if (migrationsDir) manifest.data = { provider: "supabase", migrationsDir };
8658
8815
  if (workflows.length) {
@@ -8661,12 +8818,16 @@ function starterManifest(root) {
8661
8818
  defaultBranch: gitDefaultBranch(root),
8662
8819
  workflows: Object.fromEntries(workflows.map((w) => {
8663
8820
  const name = w.slice(".github/workflows/".length);
8664
- return [name, { role: /^(deploy|publish|release)/.test(name) ? "deploy" : "ci" }];
8821
+ const steps = (readCapped(root, w) ?? "").split(/\r?\n/).filter((l) => !/^\s*#/.test(l)).join("\n");
8822
+ const deploys = /^(deploy|publish|release)/.test(name) || DEPLOY_STEPS.some((re) => re.test(steps));
8823
+ return [name, { role: deploys ? "deploy" : "ci" }];
8665
8824
  }))
8666
8825
  };
8667
8826
  }
8668
- if (existsSync3(join6(root, ".env.example"))) manifest.env = { environments: ["production"], required: [], example: ".env.example" };
8669
- manifest.change = { allowPaths: [MANIFEST, ...[...new Set(tokens.map((t) => `${t.split("/").slice(0, -1).join("/") || "."}/**`))]] };
8827
+ const envExample = ENV_EXAMPLES.find((p3) => existsSync3(join6(root, p3)));
8828
+ if (envExample) manifest.env = { environments: ["production"], required: [], example: envExample };
8829
+ const sourceDirs = tokens.filter((t) => t.role === "source").map((t) => `${t.path.split("/").slice(0, -1).join("/") || "."}/**`);
8830
+ manifest.change = { allowPaths: [MANIFEST, ...new Set(sourceDirs)] };
8670
8831
  return manifest;
8671
8832
  }
8672
8833
  function asStringList(v) {
package/dist/init.js CHANGED
@@ -25,10 +25,10 @@ import {
25
25
  saveConfig,
26
26
  savedSdkKeyFor,
27
27
  trySaveKeyToKeychain
28
- } from "./chunk-FDDSGZSC.js";
28
+ } from "./chunk-HNLTFQ4N.js";
29
29
  import {
30
30
  MUSHI_CLI_VERSION
31
- } from "./chunk-UZZUGLI2.js";
31
+ } from "./chunk-4H5TRTM3.js";
32
32
  import {
33
33
  FRAMEWORKS,
34
34
  detectFramework,
@@ -2037,7 +2037,7 @@ async function maybeOfferConnect(credentials, options, _consoleBase) {
2037
2037
  if (p.isCancel(answer) || !answer) return;
2038
2038
  const endpoint = resolveCloudEndpoint(options.endpoint);
2039
2039
  try {
2040
- const { runConnect } = await import("./connect-SEFUBQCA.js");
2040
+ const { runConnect } = await import("./connect-RIKV53NI.js");
2041
2041
  const saved = loadConfig();
2042
2042
  const result = await runConnect(
2043
2043
  {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  MUSHI_CLI_VERSION,
4
4
  MUSHI_MCP_PIN_SPEC
5
- } from "./chunk-F4EGZNKA.js";
5
+ } from "./chunk-MKUU3GHS.js";
6
6
  import "./chunk-PDX44BCA.js";
7
7
  export {
8
8
  MUSHI_CLI_VERSION,
package/dist/version.d.ts CHANGED
@@ -14,6 +14,6 @@ declare const MUSHI_CLI_VERSION: string;
14
14
  * setup refreshes the pin. Synced to packages/mcp/package.json by
15
15
  * `scripts/sync-mcp-pin.mjs` — never hand-edit the version.
16
16
  */
17
- declare const MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.24.0";
17
+ declare const MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.24.2";
18
18
 
19
19
  export { MUSHI_CLI_VERSION, MUSHI_MCP_PIN_SPEC };
package/dist/version.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  MUSHI_CLI_VERSION,
3
3
  MUSHI_MCP_PIN_SPEC
4
- } from "./chunk-UZZUGLI2.js";
4
+ } from "./chunk-4H5TRTM3.js";
5
5
  import "./chunk-3RG5ZIWI.js";
6
6
  export {
7
7
  MUSHI_CLI_VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mushi-mushi/cli",
3
- "version": "0.29.0",
3
+ "version": "0.29.2",
4
4
  "license": "MIT",
5
5
  "description": "Mushi CLI: SDK setup, MCP wiring, bug triage. The bug mediator for AI-built apps: plain-English diagnosis + a ready fix, in your editor.",
6
6
  "bin": {
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/version.ts
4
- var MUSHI_CLI_VERSION = true ? "0.29.0" : "0.0.0-dev";
5
- var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.24.0";
6
-
7
- export {
8
- MUSHI_CLI_VERSION,
9
- MUSHI_MCP_PIN_SPEC
10
- };
@@ -1,8 +0,0 @@
1
- // src/version.ts
2
- var MUSHI_CLI_VERSION = true ? "0.29.0" : "0.0.0-dev";
3
- var MUSHI_MCP_PIN_SPEC = "@mushi-mushi/mcp@0.24.0";
4
-
5
- export {
6
- MUSHI_CLI_VERSION,
7
- MUSHI_MCP_PIN_SPEC
8
- };