youiyoux 0.1.9 → 0.1.10

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.
@@ -4,7 +4,7 @@ import {
4
4
  loadPackage,
5
5
  readTryIndex,
6
6
  send
7
- } from "./chunk-DCBF7QQY.js";
7
+ } from "./chunk-T3KNPVQG.js";
8
8
  import {
9
9
  writeFileAtomic
10
10
  } from "./chunk-DWYDHVLZ.js";
@@ -53,7 +53,7 @@ import {
53
53
  vendoredPath,
54
54
  whereUsed,
55
55
  withFile
56
- } from "./chunk-3HON5Q5K.js";
56
+ } from "./chunk-X2YYMHR4.js";
57
57
  import {
58
58
  escapingLinks,
59
59
  within
@@ -137,6 +137,7 @@ import {
137
137
  sha256,
138
138
  shortHash,
139
139
  toPosix,
140
+ unifiedDiff,
140
141
  writeFileAtomic
141
142
  } from "./chunk-DWYDHVLZ.js";
142
143
  import {
@@ -147,8 +148,8 @@ import {
147
148
  var import_yaml4 = __toESM(require_dist(), 1);
148
149
  import { execFile as execFile5 } from "node:child_process";
149
150
  import { existsSync as existsSync5 } from "node:fs";
150
- import { appendFile as appendFile2, readFile as readFile10, rm as rm6, rmdir as rmdir3 } from "node:fs/promises";
151
- import { basename as basename5, dirname as dirname13, join as join25, relative as relative11, resolve as resolve15 } from "node:path";
151
+ import { appendFile as appendFile2, readFile as readFile10, rm as rm7, rmdir as rmdir3 } from "node:fs/promises";
152
+ import { basename as basename5, dirname as dirname13, join as join26, relative as relative11, resolve as resolve15 } from "node:path";
152
153
  import { parseArgs, promisify as promisify5 } from "node:util";
153
154
 
154
155
  // ../cli/src/check.ts
@@ -166,7 +167,7 @@ import { join as join2, relative, resolve } from "node:path";
166
167
 
167
168
  // ../cli/src/command.ts
168
169
  var COMMAND = "youiyoux";
169
- var SUBCOMMANDS = ["show", "where", "bom", "check", "baseline", "rules", "plan", "migrate", "init", "adopt", "status", "system", "sync", "link", "unlink", "scan", "watch", "hooks", "agents", "mcp", "ui", "library", "discover", "index", "report", "render", "screens", "requests", "detect", "build", "parity", "schema", "inventory", "gaps", "help"];
170
+ var SUBCOMMANDS = ["show", "where", "bom", "check", "baseline", "rules", "plan", "migrate", "upgrade", "init", "adopt", "status", "system", "sync", "link", "unlink", "scan", "watch", "hooks", "agents", "mcp", "ui", "library", "discover", "index", "report", "render", "screens", "requests", "detect", "build", "parity", "schema", "inventory", "gaps", "help"];
170
171
 
171
172
  // ../cli/src/agents.ts
172
173
  var import_yaml = __toESM(require_dist(), 1);
@@ -801,6 +802,7 @@ async function readLock(root) {
801
802
  var Writer = class {
802
803
  actions = [];
803
804
  files = {};
805
+ contents = /* @__PURE__ */ new Map();
804
806
  project;
805
807
  options;
806
808
  previous;
@@ -813,6 +815,7 @@ var Writer = class {
813
815
  return join6(this.project.root, file);
814
816
  }
815
817
  async write(file, content) {
818
+ this.contents.set(file, content);
816
819
  if (!this.options.dryRun) await writeFileAtomic(this.path(file), content);
817
820
  }
818
821
  record(action) {
@@ -985,7 +988,7 @@ async function syncProject(project2, options = {}) {
985
988
  };
986
989
  if (!options.dryRun) await writeFileAtomic(join6(project2.root, LOCK_FILE), `${JSON.stringify(lock, null, 2)}
987
990
  `);
988
- return { actions: writer.actions, lock, unknownTools: unknownToolMentions(project2) };
991
+ return { actions: writer.actions, lock, unknownTools: unknownToolMentions(project2), contents: writer.contents };
989
992
  }
990
993
  async function sameFile(a, b) {
991
994
  const [x, y] = await Promise.all([realpath(a).catch(() => null), realpath(b).catch(() => null)]);
@@ -2106,7 +2109,7 @@ async function libraryLicence(id) {
2106
2109
  }
2107
2110
  }
2108
2111
  async function startRuleEditor(options) {
2109
- const { FileStore, RuleWorkflow, serveWorkflow } = await import("./src-EUVBYTKY.js");
2112
+ const { FileStore, RuleWorkflow, serveWorkflow } = await import("./src-6SNQVIZS.js");
2110
2113
  const projectRoot = resolve6(options.project);
2111
2114
  const load2 = { ...options.config ? { configPath: resolve6(options.config) } : {}, ...options.design ? { designRoot: resolve6(options.design) } : {}, ...options.root ? { productRoot: resolve6(options.root) } : {} };
2112
2115
  const project2 = await loadProject(projectRoot, load2);
@@ -2650,14 +2653,186 @@ async function extractSystem(project2, dir, options = {}) {
2650
2653
  }
2651
2654
  }
2652
2655
 
2656
+ // ../cli/src/upgrade.ts
2657
+ import { lstat as lstat2, rm as rm5 } from "node:fs/promises";
2658
+ import { join as join16 } from "node:path";
2659
+ var LOCK_FILE2 = "youi.lock.json";
2660
+ var WRITES = /* @__PURE__ */ new Set(["created", "updated", "merged", "adopted", "removed"]);
2661
+ function compareVersions(a, b) {
2662
+ const parse = (v) => {
2663
+ const [core = "", pre = ""] = v.replace(/^v/, "").split("-", 2);
2664
+ return [core.split(".").slice(0, 3).map((n) => Number(n) || 0), pre];
2665
+ };
2666
+ const [[x, xp], [y, yp]] = [parse(a), parse(b)];
2667
+ for (let i = 0; i < 3; i++) if ((x[i] ?? 0) !== (y[i] ?? 0)) return (x[i] ?? 0) - (y[i] ?? 0);
2668
+ if (xp === yp) return 0;
2669
+ return xp === "" ? 1 : yp === "" ? -1 : xp < yp ? -1 : 1;
2670
+ }
2671
+ function admits(range, version) {
2672
+ const parts = range.trim().split(/\s+/);
2673
+ const results = parts.map((part) => {
2674
+ if (part === "*" || part === "x") return true;
2675
+ const xr = /^v?(\d+)(?:\.(\d+|x))?(?:\.(x))?$/.exec(part);
2676
+ if (xr && (xr[2] === "x" || xr[3] === "x" || xr[2] === void 0)) {
2677
+ const [major, minor] = version.split(".").map(Number);
2678
+ return major === Number(xr[1]) && (xr[2] === void 0 || xr[2] === "x" || minor === Number(xr[2]));
2679
+ }
2680
+ const op = /^(\^|~|>=|<=|>|<|=)?v?(\d+\.\d+\.\d+(?:-[\w.]+)?)$/.exec(part);
2681
+ if (!op) return null;
2682
+ const [, kind = "=", base = ""] = op;
2683
+ const cmp = compareVersions(version, base);
2684
+ const [bMajor, bMinor] = base.split(".").map(Number);
2685
+ const [vMajor, vMinor] = version.split(".").map(Number);
2686
+ if (kind === "^") return cmp >= 0 && (bMajor === 0 ? vMajor === 0 && vMinor === bMinor : vMajor === bMajor);
2687
+ if (kind === "~") return cmp >= 0 && vMajor === bMajor && vMinor === bMinor;
2688
+ return { "=": cmp === 0, ">=": cmp >= 0, "<=": cmp <= 0, ">": cmp > 0, "<": cmp < 0 }[kind] ?? null;
2689
+ });
2690
+ return results.includes(null) ? null : results.every(Boolean);
2691
+ }
2692
+ function pendingMigrations(project2, lock) {
2693
+ const entries = Object.entries(lock.files).flatMap(([file, entry]) => entry.kind === "vendored" ? [{ file, ...entry }] : []);
2694
+ const planned = [];
2695
+ for (const { contract, migrations } of project2.system.components) {
2696
+ const entry = entries.find((e) => e.file === vendoredPath(project2, contract.source.file) && e.elements.includes(contract.id)) ?? entries.filter((e) => e.elements.includes(contract.id)).sort((a, b) => a.elements.length - b.elements.length)[0];
2697
+ if (!entry) continue;
2698
+ let at = entry.version;
2699
+ for (const spec of [...migrations].filter((m) => compareVersions(m.to, entry.version) > 0 && compareVersions(m.to, contract.version) <= 0).sort((a, b) => compareVersions(a.to, b.to) || a.id.localeCompare(b.id))) {
2700
+ planned.push({ spec, at, mismatch: admits(spec.from, at) === false });
2701
+ at = spec.to;
2702
+ }
2703
+ }
2704
+ return planned.sort((a, b) => compareVersions(a.spec.to, b.spec.to) || a.spec.id.localeCompare(b.spec.id));
2705
+ }
2706
+ var Snapshot = class {
2707
+ saved = /* @__PURE__ */ new Map();
2708
+ root;
2709
+ constructor(root) {
2710
+ this.root = root;
2711
+ }
2712
+ async keep(files) {
2713
+ for (const file of files) if (!this.saved.has(file)) this.saved.set(file, await readTextOrNull(join16(this.root, file)));
2714
+ }
2715
+ /** A file's content before a step wrote it, unless it was kept already. */
2716
+ remember(file, content) {
2717
+ if (!this.saved.has(file)) this.saved.set(file, content);
2718
+ }
2719
+ /** Put back each file that changed; those that could not be are returned, to name them. */
2720
+ async restore() {
2721
+ const stuck = [];
2722
+ for (const [file, content] of this.saved) {
2723
+ const path = join16(this.root, file);
2724
+ try {
2725
+ if (content !== null) {
2726
+ if (await readTextOrNull(path) !== content) await writeFileAtomic(path, content);
2727
+ } else if (await lstat2(path).then((s) => s.isFile(), () => false)) await rm5(path);
2728
+ } catch {
2729
+ stuck.push(file);
2730
+ }
2731
+ }
2732
+ return stuck;
2733
+ }
2734
+ };
2735
+ var gateFailures = (result) => result.gates.filter((g) => !g.ok).map((g) => `${g.name}: ${g.detail}`).join("; ");
2736
+ async function withRef(configFile, ref) {
2737
+ const text = await readTextOrNull(configFile) ?? "{}";
2738
+ const config = JSON.parse(text);
2739
+ return `${JSON.stringify({ ...config, source: { ...config.source, ref } }, null, 2)}
2740
+ `;
2741
+ }
2742
+ async function upgradeProject(project2, options = {}) {
2743
+ const lock = await readLock(project2.root);
2744
+ const source = project2.config.source;
2745
+ const system = { id: project2.system.config.id, name: project2.system.config.name };
2746
+ const to = { version: project2.system.config.version, commit: project2.designCommit ?? null, ref: options.to ?? ("git" in source ? source.ref : null) };
2747
+ const from = { version: lock?.systemVersion ?? null, commit: lock?.sourceCommit ?? null };
2748
+ const result = (status, parts, next2) => ({ status, system, from, to, sync: parts.sync ?? [], migrations: parts.migrations ?? [], blocked: parts.blocked ?? [], next: next2 });
2749
+ if (!lock) return result("blocked", { blocked: ["this product has never been synced with its System, so there is no earlier version to upgrade from"] }, "youiyoux sync");
2750
+ if (lock.system !== system.id) return result("blocked", { blocked: [`youi.lock.json is for System ${lock.system}, and the config names ${system.id}: an upgrade moves within one System`] }, "youiyoux sync, to switch Systems");
2751
+ const dry = await syncProject(project2, { dryRun: true });
2752
+ const conflicts = dry.actions.filter((a) => a.action === "conflict");
2753
+ const sync = dry.actions.filter((a) => WRITES.has(a.action) || a.action === "conflict" || a.action === "kept-local");
2754
+ const planned = pendingMigrations(project2, lock);
2755
+ const blocked = [
2756
+ ...conflicts.map((a) => `${a.file}: ${a.detail ?? "conflicts with upstream"}`),
2757
+ ...planned.filter((p) => p.mismatch).map((p) => `${p.spec.id} migrates from ${p.spec.from}, but ${p.spec.element} would be at ${p.at} here: no migration takes it from ${p.at} to ${p.spec.from}`)
2758
+ ];
2759
+ if (blocked.length > 0) return result("blocked", { sync, blocked }, conflicts.length > 0 ? "youiyoux sync: resolve the conflicts it reports, then youiyoux sync --adopt records them, then youiyoux upgrade" : "ask the System's owners for the missing migration, or migrate by hand, then youiyoux sync");
2760
+ let staged = Object.fromEntries(dry.actions.filter((a) => a.role === "component" && dry.contents.has(a.file)).map((a) => [a.file, dry.contents.get(a.file)]));
2761
+ const previews = [];
2762
+ for (const { spec } of planned) {
2763
+ const preview = await runMigration({ ...project2, staged }, spec);
2764
+ previews.push(preview);
2765
+ if (preview.status === "rejected") return result("blocked", { sync, migrations: previews, blocked: [`${spec.id} would not hold: ${gateFailures(preview)}`] }, "fix what the failing gate names, or ask the System's owners; nothing was written");
2766
+ staged = { ...staged, ...Object.fromEntries(preview.changes.map((c) => [c.file, c.after])) };
2767
+ }
2768
+ const ref = options.to !== void 0 && "git" in source && options.to !== source.ref ? options.to : null;
2769
+ const changes = sync.some((a) => WRITES.has(a.action)) || previews.some((m) => m.status !== "noop") || ref !== null || lock.systemVersion !== to.version;
2770
+ if (!changes) return result("current", { sync, migrations: previews }, "nothing to do");
2771
+ if (!options.write) return result("preview", { sync, migrations: previews }, `youiyoux upgrade${options.to !== void 0 ? ` --to ${options.to}` : ""} --write`);
2772
+ const configFile = project2.configFile ?? join16(project2.root, PROJECT_FILE);
2773
+ const snapshot = new Snapshot(project2.root);
2774
+ const configBefore = await readTextOrNull(configFile);
2775
+ await snapshot.keep([LOCK_FILE2, ...dry.contents.keys(), ...dry.actions.filter((a) => a.action === "removed").map((a) => a.file), ...previews.flatMap((m) => m.changes.map((c) => c.file))]);
2776
+ const fail = async (why, done) => {
2777
+ const stuck = await snapshot.restore();
2778
+ if (ref !== null && configBefore !== null) await writeFileAtomic(configFile, configBefore).catch(() => stuck.push(PROJECT_FILE));
2779
+ const back = stuck.length === 0 ? "every file the upgrade wrote was put back" : `the files it wrote were put back except ${stuck.join(", ")}: restore those from git`;
2780
+ return result("blocked", { sync, migrations: previews, ...done, blocked: [`${why}; ${back}`] }, "run youiyoux upgrade again to see what changed");
2781
+ };
2782
+ try {
2783
+ if (ref !== null) await writeFileAtomic(configFile, await withRef(configFile, ref));
2784
+ const synced = await syncProject(project2);
2785
+ const late = synced.actions.filter((a) => a.action === "conflict");
2786
+ if (late.length > 0) return await fail(`the sync conflicted in ${late.map((a) => a.file).join(", ")}`, {});
2787
+ const applied = [];
2788
+ for (const { spec } of planned) {
2789
+ const run7 = await runMigration(project2, spec, { write: true });
2790
+ applied.push(run7);
2791
+ for (const change of run7.changes) snapshot.remember(change.file, change.before);
2792
+ if (run7.status === "rejected") return await fail(`${spec.id} did not hold on the written files: ${gateFailures(run7)}`, { migrations: applied });
2793
+ }
2794
+ const residuals = applied.reduce((n, m) => n + m.residuals.length, 0);
2795
+ return result("upgraded", { sync: synced.actions.filter((a) => WRITES.has(a.action) || a.action === "kept-local"), migrations: applied }, residuals > 0 ? `fix the ${residuals === 1 ? "site" : `${residuals} sites`} listed for a person, then youiyoux check` : "youiyoux check");
2796
+ } catch (error) {
2797
+ return fail(error instanceof Error ? error.message : String(error), {});
2798
+ }
2799
+ }
2800
+ var ACTION = { created: style.ok, updated: style.live, merged: style.live, adopted: style.ok, removed: style.live, "kept-local": style.warn, conflict: style.error };
2801
+ function renderUpgrade(r, showDiff) {
2802
+ const version = (v) => v === null ? "never synced" : `v${v}`;
2803
+ const move = r.from.version === r.to.version ? `${version(r.to.version)}${r.from.commit && r.to.commit && r.from.commit !== r.to.commit ? style.dim(` (${r.from.commit.slice(0, 7)} \u2192 ${r.to.commit.slice(0, 7)})`) : ""}` : `${version(r.from.version)} \u2192 v${r.to.version}`;
2804
+ const verdict = { current: style.ok("up to date"), preview: style.live("preview: nothing written"), upgraded: style.ok("upgraded"), blocked: style.error("blocked: nothing written") }[r.status];
2805
+ const lines = [`${style.accent("upgrade")} ${r.system.name} ${move}${r.to.ref ? style.dim(` \xB7 ref ${r.to.ref}`) : ""} ${verdict}`, ""];
2806
+ const row = (a) => ` ${padEnd((ACTION[a.action] ?? style.dim)(a.action), 11)} ${a.file}${a.detail ? style.dim(` ${a.detail}`) : ""}`;
2807
+ const generated = r.sync.filter((a) => a.role !== "component" && a.action !== "conflict");
2808
+ lines.push(style.bold("sync"), ...r.sync.length === 0 ? [style.dim(" nothing to bring")] : r.sync.filter((a) => !generated.includes(a)).map(row));
2809
+ if (generated.length === 1) lines.push(row(generated[0]));
2810
+ else if (generated.length > 1) lines.push(` ${padEnd(style.live("updated"), 11)} ${plural(generated.length, "generated file")}${style.dim(` ${generated.slice(0, 3).map((a) => a.file).join(", ")}${generated.length > 3 ? ", \u2026" : ""}`)}`);
2811
+ lines.push("", style.bold("migrations"));
2812
+ if (r.migrations.length === 0) lines.push(style.dim(r.status === "blocked" && r.sync.length > 0 ? " not run" : r.status === "current" ? " none pending" : " none: no component this product has changed its API in this release"));
2813
+ for (const m of r.migrations) {
2814
+ const mark = m.status === "rejected" ? style.error("\u2716") : m.status === "noop" ? style.dim("\xB7") : style.ok("\u2713");
2815
+ const what = m.status === "noop" ? style.dim("nothing here uses what it changes") : `${plural(m.edited, "site")} rewritten in ${plural(m.changes.length, "file")}${m.residuals.length > 0 ? ` \xB7 ${style.warn(`${plural(m.residuals.length, "site")} for a person`)}` : ""}`;
2816
+ lines.push(` ${mark} ${m.migration} ${what}`);
2817
+ for (const gate of m.gates.filter((g) => !g.ok)) lines.push(` ${style.error(gate.name)} ${style.dim(gate.detail)}`);
2818
+ for (const residual of m.residuals) lines.push(` ${style.dim(`${residual.file}:${residual.line}`)} ${residual.reason}`);
2819
+ }
2820
+ const files = /* @__PURE__ */ new Map();
2821
+ for (const change of r.migrations.flatMap((m) => m.changes)) files.set(change.file, { before: files.get(change.file)?.before ?? change.before, after: change.after });
2822
+ if (showDiff) for (const [file, { before, after }] of files) lines.push("", ...unifiedDiff(file, before, after).trimEnd().split("\n").map((l) => l.startsWith("+") && !l.startsWith("+++") ? style.ok(l) : l.startsWith("-") && !l.startsWith("---") ? style.error(l) : style.dim(l)));
2823
+ if (r.blocked.length > 0) lines.push("", ...r.blocked.map((b) => `${style.error("\u2716")} ${b}`));
2824
+ lines.push("", `${style.bold("Next:")} ${r.next}`);
2825
+ return lines.join("\n");
2826
+ }
2827
+
2653
2828
  // ../cli/src/status.ts
2654
2829
  import { realpath as realpath5 } from "node:fs/promises";
2655
- import { dirname as dirname9, join as join16, relative as relative8, resolve as resolve10 } from "node:path";
2830
+ import { dirname as dirname9, join as join17, relative as relative8, resolve as resolve10 } from "node:path";
2656
2831
  var placeOf = (cwd, root) => {
2657
2832
  const rel = relative8(cwd, root) || ".";
2658
2833
  return rel.split(/[\\/]/).filter((part) => part === "..").length > 1 ? resolve10(root) : rel;
2659
2834
  };
2660
- var WRITES = /* @__PURE__ */ new Set(["created", "updated", "merged", "adopted", "conflict", "removed"]);
2835
+ var WRITES2 = /* @__PURE__ */ new Set(["created", "updated", "merged", "adopted", "conflict", "removed"]);
2661
2836
  function sourceOf(project2) {
2662
2837
  if (project2.linked) return `your checkout ${project2.linked}`;
2663
2838
  const source = project2.config.source;
@@ -2665,9 +2840,10 @@ function sourceOf(project2) {
2665
2840
  if ("git" in source) return `git ${source.git} at ${source.ref}`;
2666
2841
  return resolve10(project2.root) === resolve10(project2.repo.root) ? "this repo" : `path ${source.path}`;
2667
2842
  }
2668
- function nextStep(s) {
2843
+ function nextStep(s, migrations) {
2669
2844
  if (s.sync.state === "never") return "youiyoux sync: this product has never been synced with its System";
2670
2845
  if (s.sync.state === "conflict") return "youiyoux sync: resolve the conflicts it reports, then youiyoux sync --adopt records them";
2846
+ if (migrations > 0) return `youiyoux upgrade: ${s.system.name} v${s.system.version} comes with ${plural(migrations, "migration")} for this product's code, which upgrade runs with the sync`;
2671
2847
  if (s.sync.state === "behind") return `youiyoux sync: ${plural(s.sync.changes.length, "file")} would change`;
2672
2848
  if (s.check.incomplete) return "youiyoux check: some files or rules could not be checked, and it says which";
2673
2849
  if (s.check.errors > 0) return `youiyoux check: fix ${plural(s.check.errors, "error")}`;
@@ -2678,13 +2854,13 @@ function nextStep(s) {
2678
2854
  async function projectStatus(project2, cwd = process.cwd()) {
2679
2855
  const lock = await readLock(project2.root);
2680
2856
  const { actions } = await syncProject(project2, { dryRun: true });
2681
- const changes = actions.filter((a) => WRITES.has(a.action)).map((a) => ({ file: a.file, action: a.action }));
2857
+ const changes = actions.filter((a) => WRITES2.has(a.action)).map((a) => ({ file: a.file, action: a.action }));
2682
2858
  const baselineFile2 = baselinePath(project2);
2683
2859
  const check = await runCheck(project2, { baseline: await readTextOrNull(baselineFile2) === null ? null : baselineFile2 });
2684
2860
  const comparison = check.baseline?.comparison;
2685
2861
  const counted = comparison ? [...comparison.new, ...comparison.regressed] : check.violations;
2686
2862
  const usages = check.scan.report.usages;
2687
- const { RequestStore } = await import("./src-EUVBYTKY.js");
2863
+ const { RequestStore } = await import("./src-6SNQVIZS.js");
2688
2864
  const requests = await new RequestStore(project2.root, project2.config.id).list();
2689
2865
  const status = {
2690
2866
  id: project2.config.id,
@@ -2702,7 +2878,7 @@ async function projectStatus(project2, cwd = process.cwd()) {
2702
2878
  components: { system: project2.system.components.length, used: new Set(usages.map((u) => u.element)).size, sites: usages.length },
2703
2879
  requests: { open: requests.requests.filter((r) => r.status === "open").length, addressed: requests.requests.filter((r) => r.status === "addressed").length, unreadable: requests.unreadable.length }
2704
2880
  };
2705
- return { ...status, next: nextStep(status) };
2881
+ return { ...status, next: nextStep(status, lock ? pendingMigrations(project2, lock).length : 0) };
2706
2882
  }
2707
2883
  async function statusTargets(cwd, named2) {
2708
2884
  if (named2) return { roots: [resolve10(named2)], workspace: null };
@@ -2710,7 +2886,7 @@ async function statusTargets(cwd, named2) {
2710
2886
  if (product2) return { roots: [product2], workspace: null };
2711
2887
  const at = findUp(cwd, WORKSPACE_FILE);
2712
2888
  if (at) {
2713
- const file = join16(at, WORKSPACE_FILE);
2889
+ const file = join17(at, WORKSPACE_FILE);
2714
2890
  const workspace = await readDefinition(file, WorkspaceConfig);
2715
2891
  return { roots: workspace.projects.map((p) => resolve10(at, p)), workspace: file };
2716
2892
  }
@@ -2732,7 +2908,7 @@ async function workspaceStatus(cwd, named2) {
2732
2908
  projects.push(await projectStatus(await loadProject(root), cwd));
2733
2909
  } catch (error) {
2734
2910
  const label = placeOf(cwd, root);
2735
- projects.push({ root: label, error: error instanceof Error ? error.message : String(error), next: await readTextOrNull(join16(root, PROJECT_FILE)) === null ? `youiyoux adopt or youiyoux init --design <dir> in ${label}` : `fix ${join16(label, PROJECT_FILE)}` });
2911
+ projects.push({ root: label, error: error instanceof Error ? error.message : String(error), next: await readTextOrNull(join17(root, PROJECT_FILE)) === null ? `youiyoux adopt or youiyoux init --design <dir> in ${label}` : `fix ${join17(label, PROJECT_FILE)}` });
2736
2912
  }
2737
2913
  }
2738
2914
  return { schema: "youi.status/v1", generatedAt: (/* @__PURE__ */ new Date()).toISOString(), workspace: workspace ? relative8(cwd, workspace) || WORKSPACE_FILE : null, projects };
@@ -2829,14 +3005,14 @@ async function startWorkspaceHub(options) {
2829
3005
  }
2830
3006
 
2831
3007
  // ../cli/src/index-store.ts
2832
- import { appendFile, mkdir as mkdir4, readFile as readFile6, stat as stat2, rename as rename2, mkdtemp as mkdtemp4, rm as rm5 } from "node:fs/promises";
2833
- import { dirname as dirname10, join as join17, resolve as resolve11 } from "node:path";
3008
+ import { appendFile, mkdir as mkdir4, readFile as readFile6, stat as stat2, rename as rename2, mkdtemp as mkdtemp4, rm as rm6 } from "node:fs/promises";
3009
+ import { dirname as dirname10, join as join18, resolve as resolve11 } from "node:path";
2834
3010
  var SOURCES_FILE = "index-sources.json";
2835
3011
  var SCANS_LOG = "scans.jsonl";
2836
3012
  var EMPTY = { discover: null, inventories: [], projects: [] };
2837
3013
  async function readIndexSources(home) {
2838
3014
  try {
2839
- const raw = JSON.parse(await readFile6(join17(home, SOURCES_FILE), "utf8"));
3015
+ const raw = JSON.parse(await readFile6(join18(home, SOURCES_FILE), "utf8"));
2840
3016
  return { discover: raw.discover ?? null, inventories: raw.inventories ?? [], projects: raw.projects ?? [] };
2841
3017
  } catch {
2842
3018
  return EMPTY;
@@ -2849,14 +3025,14 @@ async function noteSource(home, change) {
2849
3025
  inventories: change.inventory && !sources.inventories.includes(change.inventory) ? [...sources.inventories, change.inventory] : sources.inventories,
2850
3026
  projects: change.project ? [...sources.projects.filter((p) => p.root !== change.project.root), change.project] : sources.projects
2851
3027
  };
2852
- await writeFileAtomic(join17(home, SOURCES_FILE), `${JSON.stringify(next2, null, 2)}
3028
+ await writeFileAtomic(join18(home, SOURCES_FILE), `${JSON.stringify(next2, null, 2)}
2853
3029
  `);
2854
3030
  }
2855
3031
  async function recordInventory(store, home, report, file) {
2856
3032
  const run7 = inventoryRun(report, resolve11(file));
2857
3033
  const logged = { run: run7.run, source: run7.source, scannedAt: run7.scannedAt, projects: run7.projects, families: run7.families };
2858
3034
  await mkdir4(home, { recursive: true });
2859
- await appendFile(join17(home, SCANS_LOG), `${JSON.stringify({ schema: "youi.scan-log/v1", ...logged })}
3035
+ await appendFile(join18(home, SCANS_LOG), `${JSON.stringify({ schema: "youi.scan-log/v1", ...logged })}
2860
3036
  `);
2861
3037
  await store.recordInventory(run7);
2862
3038
  await noteSource(home, { inventory: run7.source });
@@ -2867,7 +3043,7 @@ async function recordProject(store, project2, usage) {
2867
3043
  await store.replaceGraph(`project:${project2.root}`, projectGraph({ project: project2.config.id, rules: project2.system.rules, components: project2.system.components.map((c) => ({ id: c.contract.id, name: c.contract.name })), usage }));
2868
3044
  }
2869
3045
  async function readLog(home) {
2870
- const text = await readFile6(join17(home, SCANS_LOG), "utf8").catch(() => "");
3046
+ const text = await readFile6(join18(home, SCANS_LOG), "utf8").catch(() => "");
2871
3047
  return text.split("\n").flatMap((line) => {
2872
3048
  if (!line.trim()) return [];
2873
3049
  try {
@@ -2884,7 +3060,7 @@ async function rebuildIndex(path, options = {}) {
2884
3060
  const home = indexHome(path, env);
2885
3061
  await mkdir4(dirname10(path), { recursive: true });
2886
3062
  const scratch = !env.DATABASE_URL ? await mkdtemp4(`${path}.rebuild-`) : null;
2887
- const target = scratch ? join17(scratch, "index.db") : path;
3063
+ const target = scratch ? join18(scratch, "index.db") : path;
2888
3064
  const store = scratch ? await openSqlite(target) : await sharedStore(path, env);
2889
3065
  try {
2890
3066
  if (env.DATABASE_URL) await store.reset();
@@ -2892,7 +3068,7 @@ async function rebuildIndex(path, options = {}) {
2892
3068
  const sources = await readIndexSources(home);
2893
3069
  const cache = options.discoverCache ?? sources.discover;
2894
3070
  let discover = { cache, chosen: 0, all: 0 };
2895
- if (cache && await stat2(join17(cache, "index.json")).then(() => true, () => false)) {
3071
+ if (cache && await stat2(join18(cache, "index.json")).then(() => true, () => false)) {
2896
3072
  const loaded = await ingestCatalog(store, cache);
2897
3073
  discover = { cache, chosen: loaded.chosen, all: loaded.all };
2898
3074
  }
@@ -2920,7 +3096,7 @@ async function rebuildIndex(path, options = {}) {
2920
3096
  }
2921
3097
  try {
2922
3098
  const project2 = await loadProject(source.root, source.options);
2923
- const usage = ScanReport.safeParse(await readJson(source.usage ?? join17(project2.root, ".youi/usage.json")));
3099
+ const usage = ScanReport.safeParse(await readJson(source.usage ?? join18(project2.root, ".youi/usage.json")));
2924
3100
  await recordProject(store, project2, usage.success ? usage.data : null);
2925
3101
  projects++;
2926
3102
  } catch (error) {
@@ -2955,7 +3131,7 @@ async function rebuildIndex(path, options = {}) {
2955
3131
  } finally {
2956
3132
  if (scratch) {
2957
3133
  await store.close();
2958
- await rm5(scratch, { recursive: true, force: true });
3134
+ await rm6(scratch, { recursive: true, force: true });
2959
3135
  }
2960
3136
  }
2961
3137
  }
@@ -3139,7 +3315,7 @@ function renderAdoptionRequest(request) {
3139
3315
  // ../cli/src/report/run.ts
3140
3316
  import { randomBytes as randomBytes3 } from "node:crypto";
3141
3317
  import { mkdir as mkdir5, rename as rename3, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
3142
- import { join as join24, relative as relative10, resolve as resolve14 } from "node:path";
3318
+ import { join as join25, relative as relative10, resolve as resolve14 } from "node:path";
3143
3319
 
3144
3320
  // ../cli/src/report/card.ts
3145
3321
  import { deflateSync } from "node:zlib";
@@ -3375,7 +3551,7 @@ function drawCard(input) {
3375
3551
 
3376
3552
  // ../cli/src/report/model.ts
3377
3553
  import { readFile as readFile8 } from "node:fs/promises";
3378
- import { join as join21 } from "node:path";
3554
+ import { join as join22 } from "node:path";
3379
3555
 
3380
3556
  // ../cli/src/report/filters.ts
3381
3557
  var SHOWCASE_GLOBS = ["**/{__stories__,.storybook,storybook,storybook-static,example,examples,demo,demos,playground,showcase,showcases}/**", "**/*.stories.*", "**/*.story.*"];
@@ -3502,11 +3678,11 @@ function publicLook(caption) {
3502
3678
 
3503
3679
  // ../cli/src/report/groups.ts
3504
3680
  import { existsSync as existsSync3 } from "node:fs";
3505
- import { join as join19 } from "node:path";
3681
+ import { join as join20 } from "node:path";
3506
3682
 
3507
3683
  // ../cli/src/report/imports.ts
3508
3684
  import { realpathSync } from "node:fs";
3509
- import { dirname as dirname11, join as join18, relative as relative9, resolve as resolve12 } from "node:path";
3685
+ import { dirname as dirname11, join as join19, relative as relative9, resolve as resolve12 } from "node:path";
3510
3686
  import ts from "typescript";
3511
3687
  var resolvers = /* @__PURE__ */ new Map();
3512
3688
  function resolverOf(root) {
@@ -3525,13 +3701,13 @@ function clearImportCache() {
3525
3701
  }
3526
3702
  async function verifiedImport(root, keeper, from, suggested) {
3527
3703
  const { options, cache } = resolverOf(root);
3528
- let local = relative9(dirname11(join18(root, from)), join18(root, keeper)).replaceAll("\\", "/").replace(/\.(tsx?|jsx?|mjs)$/, "");
3704
+ let local = relative9(dirname11(join19(root, from)), join19(root, keeper)).replaceAll("\\", "/").replace(/\.(tsx?|jsx?|mjs)$/, "");
3529
3705
  if (!local.startsWith(".")) local = `./${local}`;
3530
3706
  for (const specifier of /* @__PURE__ */ new Set([suggested, local])) {
3531
3707
  const found = ts.resolveModuleName(specifier, resolve12(root, from), options, ts.sys, cache).resolvedModule?.resolvedFileName;
3532
3708
  if (found) {
3533
3709
  try {
3534
- if (realpathSync(found) === realpathSync(join18(root, keeper))) return specifier;
3710
+ if (realpathSync(found) === realpathSync(join19(root, keeper))) return specifier;
3535
3711
  } catch {
3536
3712
  }
3537
3713
  }
@@ -3939,7 +4115,7 @@ function factsOf(project2, id, modules, eligible, workspaceNames, dependencies,
3939
4115
  if (dirs.has(file.slice(0, at))) break;
3940
4116
  dirs.add(file.slice(0, at));
3941
4117
  }
3942
- const roots = [...dirs].filter((dir) => existsSync3(join19(project2.root, dir, "package.json"))).sort((a, b) => b.length - a.length);
4118
+ const roots = [...dirs].filter((dir) => existsSync3(join20(project2.root, dir, "package.json"))).sort((a, b) => b.length - a.length);
3943
4119
  const nested = (file) => roots.find((dir) => file.startsWith(`${dir}/`)) ?? "";
3944
4120
  return { project: project2, id, dependencies, packageImports, jsxCounts, eligible, twins, dirs, importer, packageOf: nested };
3945
4121
  }
@@ -3947,11 +4123,11 @@ function factsOf(project2, id, modules, eligible, workspaceNames, dependencies,
3947
4123
  // ../cli/src/report/projects.ts
3948
4124
  var import_yaml3 = __toESM(require_dist(), 1);
3949
4125
  import { readFile as readFile7 } from "node:fs/promises";
3950
- import { basename as basename4, join as join20, resolve as resolve13 } from "node:path";
4126
+ import { basename as basename4, join as join21, resolve as resolve13 } from "node:path";
3951
4127
  var UI_FILES = ["**/*.{tsx,jsx,astro,vue,svelte}"];
3952
4128
  var strings = (value) => Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
3953
4129
  async function workspaceGlobs(root, pkg) {
3954
- const pnpm = await readFile7(join20(root, "pnpm-workspace.yaml"), "utf8").catch(() => null);
4130
+ const pnpm = await readFile7(join21(root, "pnpm-workspace.yaml"), "utf8").catch(() => null);
3955
4131
  if (pnpm !== null) {
3956
4132
  try {
3957
4133
  const globs2 = strings((0, import_yaml3.parse)(pnpm)?.packages);
@@ -3966,7 +4142,7 @@ async function workspaceGlobs(root, pkg) {
3966
4142
  var hasUi = async (dir) => (await findFiles(dir, UI_FILES, DEFAULT_EXCLUDE)).length > 0;
3967
4143
  async function findProjects(dir) {
3968
4144
  const root = resolve13(dir);
3969
- const pkg = await readJson(join20(root, "package.json"));
4145
+ const pkg = await readJson(join21(root, "package.json"));
3970
4146
  const name = typeof pkg?.name === "string" && pkg.name.trim() ? pkg.name.trim() : basename4(root);
3971
4147
  const single = { dir: ".", root, name: typeof pkg?.name === "string" ? pkg.name : null };
3972
4148
  const workspace = await workspaceGlobs(root, pkg);
@@ -3977,12 +4153,12 @@ async function findProjects(dir) {
3977
4153
  const projects = [];
3978
4154
  const skipped = [];
3979
4155
  for (const member of members) {
3980
- const memberRoot = join20(root, member);
4156
+ const memberRoot = join21(root, member);
3981
4157
  if (!await hasUi(memberRoot)) {
3982
4158
  skipped.push(member);
3983
4159
  continue;
3984
4160
  }
3985
- const memberPkg = await readJson(join20(memberRoot, "package.json"));
4161
+ const memberPkg = await readJson(join21(memberRoot, "package.json"));
3986
4162
  projects.push({ dir: member, root: memberRoot, name: typeof memberPkg?.name === "string" ? memberPkg.name : null });
3987
4163
  }
3988
4164
  if (projects.length === 0) return { root, name, layout: `one project (${workspace.source} names no package with UI files)`, projects: [single], skipped };
@@ -4009,7 +4185,7 @@ var Lines = class {
4009
4185
  if (!this.enabled) return { at };
4010
4186
  let lines = this.files.get(file);
4011
4187
  if (!lines) {
4012
- lines = (await readFile8(join21(this.root, file), "utf8").catch(() => "")).split("\n");
4188
+ lines = (await readFile8(join22(this.root, file), "utf8").catch(() => "")).split("\n");
4013
4189
  this.files.set(file, lines);
4014
4190
  }
4015
4191
  const code = lines[line - 1]?.trim();
@@ -4029,7 +4205,7 @@ async function modulesOf(project2, target, failed2) {
4029
4205
  for (const file of target.files) {
4030
4206
  if (isShowcase(file)) continue;
4031
4207
  try {
4032
- const module = await parseModule(file, await readFile8(join21(project2.root, file), "utf8"));
4208
+ const module = await parseModule(file, await readFile8(join22(project2.root, file), "utf8"));
4033
4209
  if (module) modules.push(module);
4034
4210
  } catch (error) {
4035
4211
  failed2.push(`${repoPath(project2.dir, file)}: ${errorText(error)}`);
@@ -4133,7 +4309,7 @@ async function analyseProject(project2, index, inventory, inventoryError, worksp
4133
4309
  incomplete.push(`Library choices were not compared (${errorText(error)}); run ${NPX} detect ${project2.dir} to see why`);
4134
4310
  }
4135
4311
  }
4136
- const pkg = await readFile8(join21(project2.root, "package.json"), "utf8").then((text) => JSON.parse(text), () => null);
4312
+ const pkg = await readFile8(join22(project2.root, "package.json"), "utf8").then((text) => JSON.parse(text), () => null);
4137
4313
  const dependencies = new Set(["dependencies", "devDependencies", "peerDependencies"].flatMap((key2) => Object.keys(pkg?.[key2] ?? {})));
4138
4314
  const importer = changeProject ? await importOf(changeProject) : () => "";
4139
4315
  const facts = factsOf(project2, projectId ?? null, modules, eligible, workspaceNames, dependencies, target?.files ?? [], importer);
@@ -4577,7 +4753,7 @@ ${model.projects.map((p) => projectSection(p, many, looks)).join("\n")}
4577
4753
  import { spawn as spawn2 } from "node:child_process";
4578
4754
  import { existsSync as existsSync4, readFileSync as readFileSync2 } from "node:fs";
4579
4755
  import { homedir as homedir2 } from "node:os";
4580
- import { dirname as dirname12, join as join22 } from "node:path";
4756
+ import { dirname as dirname12, join as join23 } from "node:path";
4581
4757
  var LOOKS_PER_PROJECT = 4;
4582
4758
  var DOWNLOAD_SIZE = "~100 MB";
4583
4759
  var DEPENDENCIES = "Install the repo's dependencies to see rendered looks";
@@ -4585,26 +4761,26 @@ var UNDRAWABLE = /not installed|loads no stylesheet|drawn from (?:its|their) (?:
4585
4761
  var playwrightDir = () => dirname12(playwrightCli());
4586
4762
  function browsersPath(env) {
4587
4763
  const set = env.PLAYWRIGHT_BROWSERS_PATH;
4588
- if (set === "0") return join22(playwrightDir(), ".local-browsers");
4764
+ if (set === "0") return join23(playwrightDir(), ".local-browsers");
4589
4765
  if (set) return set;
4590
- if (process.platform === "darwin") return join22(homedir2(), "Library/Caches/ms-playwright");
4591
- if (process.platform === "win32") return join22(env.LOCALAPPDATA ?? join22(homedir2(), "AppData/Local"), "ms-playwright");
4592
- return join22(env.XDG_CACHE_HOME ?? join22(homedir2(), ".cache"), "ms-playwright");
4766
+ if (process.platform === "darwin") return join23(homedir2(), "Library/Caches/ms-playwright");
4767
+ if (process.platform === "win32") return join23(env.LOCALAPPDATA ?? join23(homedir2(), "AppData/Local"), "ms-playwright");
4768
+ return join23(env.XDG_CACHE_HOME ?? join23(homedir2(), ".cache"), "ms-playwright");
4593
4769
  }
4594
4770
  function chromiumStatus(env = process.env) {
4595
4771
  if (env.YOUI_CHROMIUM) return { available: existsSync4(env.YOUI_CHROMIUM), where: env.YOUI_CHROMIUM };
4596
4772
  try {
4597
- const browsers = JSON.parse(readFileSync2(join22(playwrightDir(), "browsers.json"), "utf8"));
4773
+ const browsers = JSON.parse(readFileSync2(join23(playwrightDir(), "browsers.json"), "utf8"));
4598
4774
  const revision2 = browsers.browsers.find((b) => b.name === "chromium-headless-shell")?.revision;
4599
- const dir = join22(browsersPath(env), `chromium_headless_shell-${revision2}`);
4600
- return { available: revision2 !== void 0 && existsSync4(join22(dir, "INSTALLATION_COMPLETE")), where: dir };
4775
+ const dir = join23(browsersPath(env), `chromium_headless_shell-${revision2}`);
4776
+ return { available: revision2 !== void 0 && existsSync4(join23(dir, "INSTALLATION_COMPLETE")), where: dir };
4601
4777
  } catch {
4602
4778
  return { available: false, where: "playwright-core is not installed" };
4603
4779
  }
4604
4780
  }
4605
4781
  function downloadChromium() {
4606
4782
  return new Promise((resolve16) => {
4607
- const child = spawn2(process.execPath, [join22(playwrightDir(), "cli.js"), "install", "chromium-headless-shell"], { stdio: ["ignore", 2, 2] });
4783
+ const child = spawn2(process.execPath, [join23(playwrightDir(), "cli.js"), "install", "chromium-headless-shell"], { stdio: ["ignore", 2, 2] });
4608
4784
  child.on("error", () => resolve16(false));
4609
4785
  child.on("close", (code) => resolve16(code === 0));
4610
4786
  });
@@ -4620,9 +4796,9 @@ async function addLooks(model, repoRoot, options = {}) {
4620
4796
  const where2 = section.dir === "." ? "this repo" : section.dir;
4621
4797
  try {
4622
4798
  const installed = (name) => {
4623
- let dir = join22(repoRoot, section.dir);
4799
+ let dir = join23(repoRoot, section.dir);
4624
4800
  while (true) {
4625
- if (existsSync4(join22(dir, "node_modules", name, "package.json"))) return true;
4801
+ if (existsSync4(join23(dir, "node_modules", name, "package.json"))) return true;
4626
4802
  if (dir === repoRoot || dirname12(dir) === dir) return false;
4627
4803
  dir = dirname12(dir);
4628
4804
  }
@@ -4631,13 +4807,13 @@ async function addLooks(model, repoRoot, options = {}) {
4631
4807
  missing.push(where2);
4632
4808
  continue;
4633
4809
  }
4634
- const projectRoot = join22(repoRoot, section.dir);
4810
+ const projectRoot = join23(repoRoot, section.dir);
4635
4811
  const target = await loadInventoryTarget(projectRoot);
4636
4812
  if (findStylesheets(projectRoot, target.files, { tsconfig: target.tsconfig, override: target.specimenCss, templates: target.templates }).found.length === 0) {
4637
4813
  missing.push(where2);
4638
4814
  continue;
4639
4815
  }
4640
- const report = await renderShots(join22(repoRoot, section.dir), names, { download: false, base: "HEAD", ...options.executablePath ? { executablePath: options.executablePath } : {}, ...options.cache ? { cache: options.cache } : {}, ...options.log ? { log: options.log } : {} });
4816
+ const report = await renderShots(join23(repoRoot, section.dir), names, { download: false, base: "HEAD", ...options.executablePath ? { executablePath: options.executablePath } : {}, ...options.cache ? { cache: options.cache } : {}, ...options.log ? { log: options.log } : {} });
4641
4817
  const unavailable = report.notes.some((note) => UNDRAWABLE.test(note));
4642
4818
  if (unavailable) {
4643
4819
  missing.push(where2);
@@ -4709,7 +4885,7 @@ function renderMarkdown(model, reportFile) {
4709
4885
  import { realpathSync as realpathSync2 } from "node:fs";
4710
4886
  import { readFile as readFile9 } from "node:fs/promises";
4711
4887
  import { homedir as homedir3, userInfo as userInfo2 } from "node:os";
4712
- import { join as join23 } from "node:path";
4888
+ import { join as join24 } from "node:path";
4713
4889
  var REDACTED = "[redacted]";
4714
4890
  var OUTSIDE = "[path outside the repo]";
4715
4891
  var MIN_VALUE = 6;
@@ -4721,7 +4897,7 @@ async function dotenvValues(root) {
4721
4897
  const files = await findFiles(root, [".env", ".env.*", "**/.env", "**/.env.*"]).catch(() => []);
4722
4898
  const values = [];
4723
4899
  for (const file of files) {
4724
- const text = await readFile9(join23(root, file), "utf8").catch(() => "");
4900
+ const text = await readFile9(join24(root, file), "utf8").catch(() => "");
4725
4901
  for (const line of text.split(/\r?\n/)) {
4726
4902
  const match = /^\s*(?:export\s+)?[A-Za-z_][A-Za-z0-9_.-]*\s*=\s*(.*)$/.exec(line);
4727
4903
  if (!match) continue;
@@ -4894,7 +5070,7 @@ async function runReport(options = {}, io = {}) {
4894
5070
  const clean = redactor.model(model);
4895
5071
  const outDir = resolve14(options.out ?? root);
4896
5072
  await mkdir5(outDir, { recursive: true });
4897
- const files = { report: join24(outDir, REPORT_FILE), card: join24(outDir, CARD_FILE), summary: join24(outDir, SUMMARY_FILE) };
5073
+ const files = { report: join25(outDir, REPORT_FILE), card: join25(outDir, CARD_FILE), summary: join25(outDir, SUMMARY_FILE) };
4898
5074
  const t = clean.totals;
4899
5075
  const card = {
4900
5076
  repo: redactor.scrub(clean.repo),
@@ -5044,6 +5220,12 @@ ${style.bold("System")} ${style.dim("approved elements: build only with these")
5044
5220
  plan <component> --patch <json|file> classify a contract change and show its impact
5045
5221
  plan --token <id> [--value v] impact of a token change
5046
5222
  migrate <migration.yaml> [--write] [--diff] gated codemod for props and renamed or removed exports
5223
+ upgrade [--to ref] [--write] [--diff]
5224
+ move to the System's new release in one step: the sync, and each component's
5225
+ migrations past the version youi.lock.json records, run as gated dry runs on
5226
+ the components as the sync would bring them; a preview unless --write, which
5227
+ writes all of it or, if a step fails, puts every file back. --to moves a git
5228
+ source to another tag or branch (written to the config's source.ref)
5047
5229
  (imports, re-exports, uses); a dry run that prints the diff and the sites
5048
5230
  left for a person (file:line, why) unless --write; --diff shows it after --write too
5049
5231
  rules [--preview <rule.yaml>] whether each rule is checked; preview a draft rule on the current scan
@@ -5159,6 +5341,7 @@ var OPTIONS = {
5159
5341
  inventory: { type: "string" },
5160
5342
  package: { type: "string" },
5161
5343
  fork: { type: "boolean", default: false },
5344
+ to: { type: "string" },
5162
5345
  cache: { type: "string" },
5163
5346
  role: { type: "string" },
5164
5347
  license: { type: "string" },
@@ -5196,7 +5379,7 @@ async function readJsonOrFile(value) {
5196
5379
  async function cmdScan(values) {
5197
5380
  const p = await project(values);
5198
5381
  const { report } = await scanProject(p);
5199
- const out = values.out ?? join25(p.root, ".youi/usage.json");
5382
+ const out = values.out ?? join26(p.root, ".youi/usage.json");
5200
5383
  await writeFileAtomic(resolve15(out), `${JSON.stringify(report)}
5201
5384
  `);
5202
5385
  const recorded = await recordUsage(values, p, report, resolve15(out));
@@ -5243,7 +5426,7 @@ async function cmdInventory(values) {
5243
5426
  if (values.history) return cmdHistory(values, []);
5244
5427
  const dirs = inventoryDirs(values);
5245
5428
  const report = await scanInventory(values, dirs);
5246
- const out = resolve15(values.out ?? join25(dirs[0], ".youi/inventory.json"));
5429
+ const out = resolve15(values.out ?? join26(dirs[0], ".youi/inventory.json"));
5247
5430
  await writeFileAtomic(out, `${JSON.stringify(report, null, 2)}
5248
5431
  `);
5249
5432
  const recorded = await recordScan(values, report, out);
@@ -5273,7 +5456,7 @@ async function cmdIndex(values, positionals) {
5273
5456
  const [action, ...rest] = positionals;
5274
5457
  const { path, home } = indexOf(values);
5275
5458
  if (action === "path") {
5276
- if (values.json) json3({ store: storeLocation({ path }), sources: join25(home, SOURCES_FILE), scans: join25(home, SCANS_LOG) });
5459
+ if (values.json) json3({ store: storeLocation({ path }), sources: join26(home, SOURCES_FILE), scans: join26(home, SCANS_LOG) });
5277
5460
  else print(storeLocation({ path }));
5278
5461
  return 0;
5279
5462
  }
@@ -5444,15 +5627,23 @@ async function cmdLibrary(values, positionals) {
5444
5627
  async function cmdSync(values) {
5445
5628
  const p = await loadProject(values.project ?? process.cwd(), { ...loadOptions(values), refreshDesign: true });
5446
5629
  const result = await syncProject(p, { dryRun: values["dry-run"], adopt: values.adopt });
5447
- if (values.json) json3(result);
5630
+ if (values.json) json3({ actions: result.actions, lock: result.lock, unknownTools: result.unknownTools });
5448
5631
  else print([renderSync(result, values["dry-run"]), ...p.linked ? [style.warn(`! linked: the design system is your checkout ${p.linked}, not the config's source (youiyoux unlink to undo)`)] : []].join("\n"));
5449
5632
  return result.actions.some((a) => a.action === "conflict") ? 1 : 0;
5450
5633
  }
5634
+ async function cmdUpgrade(values) {
5635
+ if (values.to !== void 0 && !/^[\w][\w./-]*$/.test(values.to)) throw new UsageError(`--to ${JSON.stringify(values.to)}: expected a git tag, branch or commit`);
5636
+ const p = await loadProject(values.project ?? process.cwd(), { ...loadOptions(values), refreshDesign: true, ...values.to !== void 0 ? { ref: values.to } : {} });
5637
+ const result = await upgradeProject(p, { write: values.write, ...values.to !== void 0 ? { to: values.to } : {} });
5638
+ if (values.json) json3(result);
5639
+ else print([renderUpgrade(result, values.diff || result.status === "preview"), ...p.linked ? [style.warn(`! linked: the design system is your checkout ${p.linked}, not the config's source (youiyoux unlink to undo)`)] : []].join("\n"));
5640
+ return result.status === "blocked" ? 1 : 0;
5641
+ }
5451
5642
  async function cmdInit(values) {
5452
5643
  if (!values.design) throw new UsageError("youiyoux init --design <dir|package> (a design repo checkout, the directory holding youi.config.json, or the npm package that holds it)");
5453
5644
  const root = values.project ?? process.cwd();
5454
5645
  const design = await designArg(values.design, root);
5455
- const result = await initProject({ root, ...design, schemaDir: join25(TOOL_ROOT, "schema"), ...values.system ? { system: values.system } : {}, ...values.components ? { componentsDir: values.components } : {}, force: values.force });
5646
+ const result = await initProject({ root, ...design, schemaDir: join26(TOOL_ROOT, "schema"), ...values.system ? { system: values.system } : {}, ...values.components ? { componentsDir: values.components } : {}, force: values.force });
5456
5647
  if (!values.json) {
5457
5648
  print(`${style.ok("created")} ${result.file}`);
5458
5649
  for (const note of result.notes) print(style.dim(` \xB7 ${note}`));
@@ -5463,27 +5654,27 @@ async function cmdInit(values) {
5463
5654
  }
5464
5655
  async function cmdAdopt(values) {
5465
5656
  const root = resolve15(values.project ?? process.cwd());
5466
- if (await exists(join25(root, PROJECT_FILE))) throw new Error(`${root} already has ${PROJECT_FILE}: it follows a design system already (youiyoux sync updates it)`);
5657
+ if (await exists(join26(root, PROJECT_FILE))) throw new Error(`${root} already has ${PROJECT_FILE}: it follows a design system already (youiyoux sync updates it)`);
5467
5658
  const plan = await planAdoption({ root, ...values.components ? { componentsDir: values.components } : {}, ...values.css ? { css: values.css } : {}, ...values.system ? { system: values.system } : {}, fork: values.fork });
5468
- const taken = (await Promise.all(plan.files.map(async (f) => await exists(join25(root, f.path)) ? f.path : null))).filter((f) => f !== null);
5659
+ const taken = (await Promise.all(plan.files.map(async (f) => await exists(join26(root, f.path)) ? f.path : null))).filter((f) => f !== null);
5469
5660
  if (taken.length > 0) throw new Error(`nothing was written: ${taken.slice(0, 5).join(", ")}${taken.length > 5 ? ` and ${taken.length - 5} more` : ""} already exist${taken.length === 1 ? "s" : ""}`);
5470
5661
  if (values["dry-run"]) {
5471
5662
  if (values.json) json3(plan);
5472
5663
  else print([...adoptLines(plan, true), "", style.dim(`dry run: nothing written; would write ${plan.files.map((f) => f.path).join(", ")}${plan.stylesheet ? ` and change ${plan.stylesheet.path}` : ""}`)].join("\n"));
5473
5664
  return 0;
5474
5665
  }
5475
- const stylesheet = plan.stylesheet ? await readFile10(join25(root, plan.stylesheet.path), "utf8") : null;
5666
+ const stylesheet = plan.stylesheet ? await readFile10(join26(root, plan.stylesheet.path), "utf8") : null;
5476
5667
  try {
5477
- for (const file of plan.files) await writeFileAtomic(join25(root, file.path), file.content);
5478
- if (plan.stylesheet) await writeFileAtomic(join25(root, plan.stylesheet.path), plan.stylesheet.content);
5479
- await initProject({ root, design: root, schemaDir: join25(TOOL_ROOT, "schema"), system: plan.system.id, componentsDir: plan.componentsDir, outputs: { ...plan.outputs, targets: [...plan.outputs.targets], dark: [...plan.outputs.dark] }, tokenSources: plan.tokenSources });
5668
+ for (const file of plan.files) await writeFileAtomic(join26(root, file.path), file.content);
5669
+ if (plan.stylesheet) await writeFileAtomic(join26(root, plan.stylesheet.path), plan.stylesheet.content);
5670
+ await initProject({ root, design: root, schemaDir: join26(TOOL_ROOT, "schema"), system: plan.system.id, componentsDir: plan.componentsDir, outputs: { ...plan.outputs, targets: [...plan.outputs.targets], dark: [...plan.outputs.dark] }, tokenSources: plan.tokenSources });
5480
5671
  await syncProject(await loadProject(root), { dryRun: true });
5481
5672
  } catch (error) {
5482
- for (const file of [...plan.files.map((f) => f.path), PROJECT_FILE]) await rm6(join25(root, file), { force: true });
5483
- for (const folder of [...new Set(plan.files.map((f) => dirname13(f.path)))].sort((a, b) => b.length - a.length)) await rmdir3(join25(root, folder)).catch(() => void 0);
5484
- await rmdir3(join25(root, "design/components")).catch(() => void 0);
5485
- await rmdir3(join25(root, "design")).catch(() => void 0);
5486
- if (plan.stylesheet && stylesheet !== null) await writeFileAtomic(join25(root, plan.stylesheet.path), stylesheet);
5673
+ for (const file of [...plan.files.map((f) => f.path), PROJECT_FILE]) await rm7(join26(root, file), { force: true });
5674
+ for (const folder of [...new Set(plan.files.map((f) => dirname13(f.path)))].sort((a, b) => b.length - a.length)) await rmdir3(join26(root, folder)).catch(() => void 0);
5675
+ await rmdir3(join26(root, "design/components")).catch(() => void 0);
5676
+ await rmdir3(join26(root, "design")).catch(() => void 0);
5677
+ if (plan.stylesheet && stylesheet !== null) await writeFileAtomic(join26(root, plan.stylesheet.path), stylesheet);
5487
5678
  throw new Error(`adopt was undone, nothing kept: ${error instanceof Error ? error.message : String(error)}`);
5488
5679
  }
5489
5680
  if (!values.json) print([...adoptLines(plan), ""].join("\n"));
@@ -5557,7 +5748,7 @@ async function cmdUnlink(values) {
5557
5748
  }
5558
5749
  async function designArg(value, root) {
5559
5750
  if (existsSync5(resolve15(value)) || !PACKAGE_NAME.test(value)) return { design: value };
5560
- return { design: await designRootOf({ package: value }, join25(resolve15(root), PROJECT_FILE), root), package: value };
5751
+ return { design: await designRootOf({ package: value }, join26(resolve15(root), PROJECT_FILE), root), package: value };
5561
5752
  }
5562
5753
  async function cmdBuild(values) {
5563
5754
  const root = resolve15(values.design ?? process.cwd());
@@ -5566,10 +5757,10 @@ async function cmdBuild(values) {
5566
5757
  const output = OutputConfig.parse({ cssVarPrefix: values.prefix ?? "youi", targets: ["css-vars", "tailwind-v4", "ts", "react-native"] });
5567
5758
  const started = performance.now();
5568
5759
  const built = await buildTokens(root, system.config, output, { contracts: system.components.map((c) => c.contract) });
5569
- const out = resolve15(values.out ?? join25(root, "build", system.config.id));
5570
- const boundary = values.out ? out : join25(root, "build");
5571
- if (!within(boundary, out) || built.files.some((file) => !within(out, join25(out, file.path)))) throw new Error(`Cannot build system ${JSON.stringify(system.config.id)}: an output path leaves the output directory.`);
5572
- for (const file of built.files) await writeFileAtomic(join25(out, file.path), file.content);
5760
+ const out = resolve15(values.out ?? join26(root, "build", system.config.id));
5761
+ const boundary = values.out ? out : join26(root, "build");
5762
+ if (!within(boundary, out) || built.files.some((file) => !within(out, join26(out, file.path)))) throw new Error(`Cannot build system ${JSON.stringify(system.config.id)}: an output path leaves the output directory.`);
5763
+ for (const file of built.files) await writeFileAtomic(join26(out, file.path), file.content);
5573
5764
  if (values.json) json3({ out, files: built.files.map((f) => f.path), tokens: built.tokens.length });
5574
5765
  else print(`${style.ok("built")} ${plural(built.tokens.length, "token")} \u2192 ${built.files.map((f) => f.path).join(", ")} ${style.dim(`in ${out} (${ms(performance.now() - started)})`)}`);
5575
5766
  return 0;
@@ -5594,16 +5785,16 @@ async function cmdParity(values) {
5594
5785
  async function cmdSchema(values) {
5595
5786
  const schemas = renderJsonSchemas();
5596
5787
  if (values.check) {
5597
- const dir = join25(values.design ? resolve15(values.design) : TOOL_ROOT, "schema");
5788
+ const dir = join26(values.design ? resolve15(values.design) : TOOL_ROOT, "schema");
5598
5789
  const stale = [];
5599
- for (const { file, content } of schemas) if (await readFile10(join25(dir, file), "utf8").catch(() => null) !== content) stale.push(file);
5790
+ for (const { file, content } of schemas) if (await readFile10(join26(dir, file), "utf8").catch(() => null) !== content) stale.push(file);
5600
5791
  if (values.json) json3({ dir, stale });
5601
5792
  else print(stale.length === 0 ? `${style.ok("\u2713")} ${dir} matches this youi's schemas` : `${style.error("\u2716")} out of date in ${dir}: ${stale.join(", ")}; run youiyoux schema --write${values.design ? " --design <dir>" : ""}`);
5602
5793
  return stale.length === 0 ? 0 : 1;
5603
5794
  }
5604
5795
  if (values.write) {
5605
5796
  const root = values.design ? resolve15(values.design) : TOOL_ROOT;
5606
- for (const { file, content } of schemas) await writeFileAtomic(join25(root, "schema", file), content);
5797
+ for (const { file, content } of schemas) await writeFileAtomic(join26(root, "schema", file), content);
5607
5798
  print(`${style.ok("wrote")} ${schemas.map((s) => s.file).join(", ")}`);
5608
5799
  } else json3(Object.fromEntries(schemas.map((s) => [s.file, JSON.parse(s.content)])));
5609
5800
  return 0;
@@ -5626,7 +5817,7 @@ async function cmdHooks(values, positionals) {
5626
5817
  if (action !== "install") throw new UsageError("youiyoux hooks install [--claude] [--git] [--ci [--diff]] [--strict] or youiyoux hooks run claude|pre-commit");
5627
5818
  const p = await loadCheckProject(values.project ?? process.cwd(), loadOptions(values), !values.project);
5628
5819
  if (values.ci && !configured(p)) throw new UsageError("Run youiyoux init --design <dir> before installing the pinned CI workflow; repo-mode CI can run youiyoux check --diff <base> --strict directly");
5629
- const target = { ...hookTarget(values), project: p.root, ...configured(p) && p.configFile && p.configFile !== join25(p.root, PROJECT_FILE) ? { config: p.configFile } : {}, ...values.root !== void 0 ? { root: p.root } : {} };
5820
+ const target = { ...hookTarget(values), project: p.root, ...configured(p) && p.configFile && p.configFile !== join26(p.root, PROJECT_FILE) ? { config: p.configFile } : {}, ...values.root !== void 0 ? { root: p.root } : {} };
5630
5821
  const all = !values.claude && !values.git && !values.ci;
5631
5822
  const results = [];
5632
5823
  if (values.claude || all) results.push({ kind: "Claude Code", ...await installClaudeHook(await repoRootOf(p.root), hookCommand(TOOL_ROOT, "claude", target)) });
@@ -5645,7 +5836,7 @@ async function cmdAgents(values, positionals) {
5645
5836
  const repoRoot = await repoRootOf(projectRoot);
5646
5837
  const target = { project: projectRoot, ...values.config ? { config: resolve15(values.config) } : {}, ...values.design ? { design: resolve15(values.design) } : {}, ...values.root !== void 0 ? { root: resolve15(values.root || ".") } : {} };
5647
5838
  const server = mcpCommand(TOOL_ROOT, target);
5648
- const system = existsSync5(resolve15(values.config ?? join25(projectRoot, PROJECT_FILE))) ? await project(values) : null;
5839
+ const system = existsSync5(resolve15(values.config ?? join26(projectRoot, PROJECT_FILE))) ? await project(values) : null;
5649
5840
  const claudeServer = system && system.root === repoRoot ? { command: "node", args: mcpArgs(system) } : relativeTo(repoRoot, server);
5650
5841
  const both = !values.claude && !values.codex;
5651
5842
  const results = [];
@@ -5787,7 +5978,7 @@ async function cmdRequests(values, positionals) {
5787
5978
  const usage = "youiyoux requests [--status open|addressed|closed|all] [--route r] or youiyoux requests show <id> | reply <id> --message <text> | addressed <id> --message <what you changed>";
5788
5979
  const [action, id, ...rest] = positionals;
5789
5980
  if (rest.length > 0) throw new UsageError(usage);
5790
- const { RequestStore, requestBrief } = await import("./src-EUVBYTKY.js");
5981
+ const { RequestStore, requestBrief } = await import("./src-6SNQVIZS.js");
5791
5982
  const { project: project2, root } = await product(values);
5792
5983
  const store = new RequestStore(root, project2?.config.id ?? basename5(root));
5793
5984
  const agent = { kind: "agent", name: "youiyoux CLI" };
@@ -5820,8 +6011,8 @@ async function cmdScreens(values, positionals, io) {
5820
6011
  if (!["capture", "login"].includes(positionals[0] ?? "") || positionals.length > 1 || !values.base) throw new UsageError(usage);
5821
6012
  const { root } = await product(values);
5822
6013
  if (positionals[0] === "login") return screensLogin(values.base, values["storage-state"] ? resolve15(values["storage-state"]) : sessionFile(root), io);
5823
- const dir = resolve15(values.out ?? join25(root, ".youi/screens"));
5824
- if (!existsSync5(join25(dir, "screens.json"))) {
6014
+ const dir = resolve15(values.out ?? join26(root, ".youi/screens"));
6015
+ if (!existsSync5(join26(dir, "screens.json"))) {
5825
6016
  process.stderr.write(`${style.error("\u2716")} no screens.json in ${dir}: list the routes to capture there, as {"schema":"youiyoux.screens/v1","project":"<name>","source":"<what the app is>","capturedAt":"","viewport":{"width":1440,"height":900},"screens":[{"route":"/","path":"/"}]}
5826
6017
  `);
5827
6018
  return 1;
@@ -5886,7 +6077,7 @@ async function cmdReport(values, positionals, io) {
5886
6077
  return result.code;
5887
6078
  }
5888
6079
  async function cmdMcp(values) {
5889
- const { startStdioServer } = await import("./src-YKPJ3PII.js");
6080
+ const { startStdioServer } = await import("./src-75ODGHE3.js");
5890
6081
  await startStdioServer({ projectRoot: values.project ?? process.cwd(), ...loadOptions(values), ...values.cache ? { discoverCache: values.cache } : {} });
5891
6082
  return -1;
5892
6083
  }
@@ -5961,6 +6152,7 @@ var COMMANDS = {
5961
6152
  rules: cmdRules,
5962
6153
  plan: cmdPlan,
5963
6154
  migrate: cmdMigrate,
6155
+ upgrade: cmdUpgrade,
5964
6156
  init: cmdInit,
5965
6157
  sync: cmdSync,
5966
6158
  scan: cmdScan,
@@ -6012,7 +6204,7 @@ ${HELP}
6012
6204
  }
6013
6205
  return guarded(() => handler(located(command2, parsed.values), rest, io));
6014
6206
  }
6015
- var IN_A_PRODUCT = /* @__PURE__ */ new Set(["system", "link", "unlink", "show", "where", "bom", "check", "baseline", "rules", "plan", "migrate", "sync", "scan", "watch", "hooks", "agents", "mcp", "ui", "library", "render", "screens", "requests"]);
6207
+ var IN_A_PRODUCT = /* @__PURE__ */ new Set(["system", "link", "unlink", "show", "where", "bom", "check", "baseline", "rules", "plan", "migrate", "upgrade", "sync", "scan", "watch", "hooks", "agents", "mcp", "ui", "library", "render", "screens", "requests"]);
6016
6208
  var IN_A_DESIGN_REPO = /* @__PURE__ */ new Set(["build", "parity"]);
6017
6209
  function located(command2, values, cwd = process.cwd()) {
6018
6210
  if (IN_A_PRODUCT.has(command2) && values.project === void 0 && values.config === void 0 && values.root === void 0) {
@@ -9,7 +9,7 @@ import {
9
9
  scanProject,
10
10
  screenSlug,
11
11
  tokenImpact
12
- } from "./chunk-3HON5Q5K.js";
12
+ } from "./chunk-X2YYMHR4.js";
13
13
  import {
14
14
  buildTokens,
15
15
  contrastText,
@@ -3,7 +3,7 @@ import { createRequire as __youiRequire } from "node:module"; import { dirname a
3
3
  // src/hub-packages.js
4
4
  var PACKAGES = {
5
5
  core: () => import("./src-BYNWPNRT.js"),
6
- scanner: () => import("./src-M3OJMCUE.js"),
6
+ scanner: () => import("./src-XTNHB65M.js"),
7
7
  discover: () => import("./src-DPFJ4S2N.js"),
8
8
  tokens: () => import("./src-PURAHRCR.js")
9
9
  };
@@ -751,7 +751,13 @@ async function loadProject(root, options = {}) {
751
751
  const productRoot = options.productRoot !== void 0 ? resolve2(options.productRoot || ".") : config.root ? fromConfig(config.root) : resolve2(root);
752
752
  if (!await isDirectory2(productRoot)) throw new ProjectRootError(`product root ${productRoot} is not a directory (config ${configFile}); ${ROOT_HINT}`);
753
753
  const linked = options.designRoot ? null : await linkedDesign(productRoot);
754
- const located = options.designRoot || linked ? { root: resolve2(options.designRoot || linked), commit: null } : await locateDesign(config.source, configFile, productRoot, { refresh: options.refreshDesign });
754
+ if (options.ref !== void 0) {
755
+ if (options.designRoot || linked) throw new Error(`the design system is ${options.designRoot ? "the --design folder" : `your checkout ${linked}`}, not the config's source: check out ${options.ref} there${linked ? ", or youiyoux unlink" : ""}`);
756
+ if ("package" in config.source) throw new Error(`${config.source.package} is an npm package: install the version you want (npm install ${config.source.package}@<version>), then run this again without --to`);
757
+ if ("path" in config.source) throw new Error(`the design system is the folder ${config.source.path}: check out ${options.ref} there, then run this again without --to`);
758
+ }
759
+ const source = options.ref !== void 0 && "git" in config.source ? { ...config.source, ref: options.ref } : config.source;
760
+ const located = options.designRoot || linked ? { root: resolve2(options.designRoot || linked), commit: null } : await locateDesign(source, configFile, productRoot, { refresh: options.refreshDesign || options.ref !== void 0 });
755
761
  const repo = await loadDesignRepo(located.root);
756
762
  return {
757
763
  root: productRoot,
@@ -2408,7 +2414,7 @@ async function parseAll(project, files, overrides, parse3) {
2408
2414
  }
2409
2415
  async function scanProject(project, options = {}) {
2410
2416
  const started = performance.now();
2411
- const overrides = options.overrides ?? {};
2417
+ const overrides = { ...project.staged, ...options.overrides };
2412
2418
  const { cache } = options;
2413
2419
  cache?.beginScan();
2414
2420
  const parse3 = cache?.parse ?? parseModule;
@@ -57,8 +57,8 @@ import {
57
57
  validateContent,
58
58
  validateLibraryContent,
59
59
  validateStyleContent
60
- } from "./chunk-Y4IBE6WS.js";
61
- import "./chunk-3HON5Q5K.js";
60
+ } from "./chunk-OCZJ3JGH.js";
61
+ import "./chunk-X2YYMHR4.js";
62
62
  import "./chunk-42YJX3W5.js";
63
63
  import "./chunk-FLBRX6Y3.js";
64
64
  import "./chunk-DWYDHVLZ.js";
@@ -2,7 +2,7 @@ import { createRequire as __youiRequire } from "node:module"; import { dirname a
2
2
  import {
3
3
  RequestStore,
4
4
  requestBrief
5
- } from "./chunk-Y4IBE6WS.js";
5
+ } from "./chunk-OCZJ3JGH.js";
6
6
  import {
7
7
  PROJECT_FILE,
8
8
  ScanCache,
@@ -30,7 +30,7 @@ import {
30
30
  shotsText,
31
31
  tokenRows,
32
32
  whereUsed
33
- } from "./chunk-3HON5Q5K.js";
33
+ } from "./chunk-X2YYMHR4.js";
34
34
  import "./chunk-42YJX3W5.js";
35
35
  import {
36
36
  SHADCN_SLOTS,
@@ -188,7 +188,7 @@ import {
188
188
  whyNoLines,
189
189
  withFile,
190
190
  withoutCredentials
191
- } from "./chunk-3HON5Q5K.js";
191
+ } from "./chunk-X2YYMHR4.js";
192
192
  import {
193
193
  escapingLinks,
194
194
  relativeInside,
@@ -16,8 +16,8 @@ import {
16
16
  selectCandidates,
17
17
  thumbsDir,
18
18
  writeThumbIndex
19
- } from "./chunks/chunk-F33PKGES.js";
20
- import "./chunks/chunk-DCBF7QQY.js";
19
+ } from "./chunks/chunk-3RP664IP.js";
20
+ import "./chunks/chunk-T3KNPVQG.js";
21
21
  import "./chunks/chunk-FVVL5JCY.js";
22
22
  import "./chunks/chunk-DWYDHVLZ.js";
23
23
  import "./chunks/chunk-WNTS7ZO4.js";
@@ -2,7 +2,7 @@
2
2
  import { createRequire as __youiRequire } from "node:module"; import { dirname as __youiDir } from "node:path"; import { fileURLToPath as __youiPath } from "node:url"; const require = __youiRequire(import.meta.url); const __youiDirname = __youiDir(__youiPath(import.meta.url));
3
3
  import {
4
4
  discoverThumbsMiddleware
5
- } from "./chunks/chunk-F33PKGES.js";
5
+ } from "./chunks/chunk-3RP664IP.js";
6
6
  import {
7
7
  isLocalHost,
8
8
  loadPackage,
@@ -10,7 +10,7 @@ import {
10
10
  readTryIndex,
11
11
  send,
12
12
  tryMiddleware
13
- } from "./chunks/chunk-DCBF7QQY.js";
13
+ } from "./chunks/chunk-T3KNPVQG.js";
14
14
  import "./chunks/chunk-FVVL5JCY.js";
15
15
  import "./chunks/chunk-DWYDHVLZ.js";
16
16
  import "./chunks/chunk-WNTS7ZO4.js";
@@ -3,7 +3,7 @@ import { createRequire as __youiRequire } from "node:module"; import { dirname a
3
3
  import {
4
4
  loadPackage,
5
5
  tryProject
6
- } from "./chunks/chunk-DCBF7QQY.js";
6
+ } from "./chunks/chunk-T3KNPVQG.js";
7
7
  import "./chunks/chunk-FVVL5JCY.js";
8
8
  import "./chunks/chunk-WNTS7ZO4.js";
9
9
 
package/dist/youi.js CHANGED
@@ -2,8 +2,8 @@
2
2
  import { createRequire as __youiRequire } from "node:module"; import { dirname as __youiDir } from "node:path"; import { fileURLToPath as __youiPath } from "node:url"; const require = __youiRequire(import.meta.url); const __youiDirname = __youiDir(__youiPath(import.meta.url));
3
3
  import {
4
4
  main
5
- } from "./chunks/chunk-E5OHZJBS.js";
6
- import "./chunks/chunk-3HON5Q5K.js";
5
+ } from "./chunks/chunk-75DBKEAH.js";
6
+ import "./chunks/chunk-X2YYMHR4.js";
7
7
  import "./chunks/chunk-42YJX3W5.js";
8
8
  import "./chunks/chunk-HDJ2TOWZ.js";
9
9
  import "./chunks/chunk-6GITMASZ.js";
package/dist/youiyoux.js CHANGED
@@ -3,8 +3,8 @@ import { createRequire as __youiRequire } from "node:module"; import { dirname a
3
3
  import {
4
4
  COMMAND_NAMES,
5
5
  main
6
- } from "./chunks/chunk-E5OHZJBS.js";
7
- import "./chunks/chunk-3HON5Q5K.js";
6
+ } from "./chunks/chunk-75DBKEAH.js";
7
+ import "./chunks/chunk-X2YYMHR4.js";
8
8
  import "./chunks/chunk-42YJX3W5.js";
9
9
  import "./chunks/chunk-HDJ2TOWZ.js";
10
10
  import "./chunks/chunk-6GITMASZ.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "youiyoux",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Your agent rebuilds components you already have. youiyoux catches it: npx youiyoux turns any repo into a shareable report of near-duplicate components, hardcoded token values and off-library imports, with the fixes.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -46,9 +46,9 @@
46
46
  "typescript": "6.0.3"
47
47
  },
48
48
  "devDependencies": {
49
- "@youiyoux/cli": "0.1.9",
50
- "@youiyoux/core": "0.1.9",
51
- "@youiyoux/scanner": "0.1.9"
49
+ "@youiyoux/cli": "0.1.10",
50
+ "@youiyoux/core": "0.1.10",
51
+ "@youiyoux/scanner": "0.1.10"
52
52
  },
53
53
  "exports": {
54
54
  "./package.json": "./package.json"