youiyoux 0.1.7 → 0.1.8

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.
Files changed (66) hide show
  1. package/dist/chunks/{chunk-O66KB7BU.js → chunk-3HON5Q5K.js} +3 -3
  2. package/dist/chunks/{chunk-3SQQNQDN.js → chunk-6GITMASZ.js} +1 -1
  3. package/dist/chunks/{chunk-N6RVMQCV.js → chunk-BARSW3JO.js} +368 -148
  4. package/dist/chunks/{chunk-BITS5O6H.js → chunk-DCBF7QQY.js} +4 -4
  5. package/dist/chunks/{chunk-YWBQO7PO.js → chunk-DWYDHVLZ.js} +74 -6
  6. package/dist/chunks/{chunk-SIXL67TZ.js → chunk-F33PKGES.js} +2 -2
  7. package/dist/chunks/{chunk-TV5UX3FE.js → chunk-FLBRX6Y3.js} +1 -1
  8. package/dist/chunks/{chunk-7P4UXAIY.js → chunk-HDJ2TOWZ.js} +1 -1
  9. package/dist/chunks/{chunk-4DVBWN7H.js → chunk-Y4IBE6WS.js} +3 -3
  10. package/dist/chunks/{src-SDJCFXRI.js → src-BYNWPNRT.js} +11 -1
  11. package/dist/chunks/{src-DYZIE4XZ.js → src-DPFJ4S2N.js} +2 -2
  12. package/dist/chunks/{src-4JGIPP5A.js → src-EUVBYTKY.js} +4 -4
  13. package/dist/chunks/{src-BKPSGYS2.js → src-M3OJMCUE.js} +3 -3
  14. package/dist/chunks/{src-WP66UHF7.js → src-PURAHRCR.js} +2 -2
  15. package/dist/chunks/{src-NWPGCDGH.js → src-YKPJ3PII.js} +6 -6
  16. package/dist/chunks/{src-J6GPLCVO.js → src-ZG7JU6YJ.js} +2 -2
  17. package/dist/hub/assets/{CandidatePanel-D6Tenu7w.js → CandidatePanel-ZzbsyZo3.js} +1 -1
  18. package/dist/hub/assets/{CatalogScreen-C1tvk0sB.js → CatalogScreen-DDYlvOHy.js} +1 -1
  19. package/dist/hub/assets/{ChangesScreen-D_6yzFGP.js → ChangesScreen-C8_EyHgJ.js} +1 -1
  20. package/dist/hub/assets/{CheatSheet-Ci7mG0sm.js → CheatSheet-DfcPiXdS.js} +1 -1
  21. package/dist/hub/assets/{CommandPalette-C4twwce1.js → CommandPalette-DfFkDTVg.js} +1 -1
  22. package/dist/hub/assets/DiscoverScreen-D6NTgEgk.js +2 -0
  23. package/dist/hub/assets/{DraftEditor-DGK0Fbp1.js → DraftEditor-CUNGYbg0.js} +1 -1
  24. package/dist/hub/assets/{GapsScreen-pYuuMGEF.js → GapsScreen-CqedCj4z.js} +1 -1
  25. package/dist/hub/assets/{HomeScreen-5rm4q3ZO.js → HomeScreen-CIj1QTkw.js} +1 -1
  26. package/dist/hub/assets/{InventoryScreen-CMKKrpTo.js → InventoryScreen-CyvFXa2_.js} +1 -1
  27. package/dist/hub/assets/{LibraryScreen-CV8lwjT6.js → LibraryScreen-C4WU0f42.js} +1 -1
  28. package/dist/hub/assets/{Opened-BvT3JnuG.js → Opened-CeRWkA7c.js} +1 -1
  29. package/dist/hub/assets/{Preview-DNOsVJ9-.js → Preview-CgW-FMB7.js} +1 -1
  30. package/dist/hub/assets/{RuleDetail-BNQbhncD.js → RuleDetail-BDhZ1gCd.js} +1 -1
  31. package/dist/hub/assets/{RulesScreen-ByYZB2Rs.js → RulesScreen-D3rSo_z2.js} +1 -1
  32. package/dist/hub/assets/{ScreenImage-Dypjm8_v.js → ScreenImage-DLeA3nRh.js} +1 -1
  33. package/dist/hub/assets/{ScreensScreen-bgwSlccW.js → ScreensScreen-bGuFIyWj.js} +1 -1
  34. package/dist/hub/assets/{SearchField-DyTJpGOP.js → SearchField-DtEgq9-Q.js} +1 -1
  35. package/dist/hub/assets/{ServiceDown-f9NYtkr_.js → ServiceDown-Bn6AcA3J.js} +1 -1
  36. package/dist/hub/assets/{SpecimenCapture-DFoGMhOM.js → SpecimenCapture-p6YErF5y.js} +1 -1
  37. package/dist/hub/assets/{Specimens-BGwJj05V.js → Specimens-DuaE0WeO.js} +2 -2
  38. package/dist/hub/assets/{StackScreen-q132_QG3.js → StackScreen-DHDulDng.js} +1 -1
  39. package/dist/hub/assets/{StubScreens-DWhYvJku.js → StubScreens-CmhVNX_Z.js} +1 -1
  40. package/dist/hub/assets/{StyleScreen-CcgUv16e.js → StyleScreen-LwTqfGID.js} +1 -1
  41. package/dist/hub/assets/{Tabs-Dy1Z02s7.js → Tabs-Cbh9BCKW.js} +1 -1
  42. package/dist/hub/assets/{TokenDetail-DsYgNrPw.js → TokenDetail-BICobLK1.js} +1 -1
  43. package/dist/hub/assets/{TokensScreen-CTT0GbAH.js → TokensScreen-CyTHn55q.js} +1 -1
  44. package/dist/hub/assets/WorkspaceScreen-uPWqfklh.js +1 -0
  45. package/dist/hub/assets/{client-CIo9EOzr.js → client-BXHiuV_w.js} +1 -1
  46. package/dist/hub/assets/{discover-DGlqvyIe.js → discover-CFhyKler.js} +1 -1
  47. package/dist/hub/assets/{dist-2euSoh6x.js → dist-C6iTWL0b.js} +1 -1
  48. package/dist/hub/assets/{dist-CpzxT6kj.js → dist-DYNYuTjI.js} +1 -1
  49. package/dist/hub/assets/{dist-D8LFTd5W.js → dist-VmEpVQjP.js} +1 -1
  50. package/dist/hub/assets/{family-tiles-Cc7tTwyr.js → family-tiles-B8_onXUi.js} +1 -1
  51. package/dist/hub/assets/folder-tree-YghfTmlZ.js +1 -0
  52. package/dist/hub/assets/main-CfbpuT4Y.js +2 -0
  53. package/dist/hub/assets/{try-live-C-dwP1zF.js → try-live-CX04d2L2.js} +1 -1
  54. package/dist/hub/assets/workflow-DbBdiOmA.js +1 -0
  55. package/dist/hub/index.html +2 -1
  56. package/dist/hub-previews.js +5 -5
  57. package/dist/hub-server.js +3 -3
  58. package/dist/hub-snapshot.js +3 -2
  59. package/dist/schema/youi.status.schema.json +306 -0
  60. package/dist/schema/youi.workspace.schema.json +31 -0
  61. package/dist/youi.js +6 -6
  62. package/dist/youiyoux.js +6 -6
  63. package/package.json +4 -4
  64. package/dist/hub/assets/DiscoverScreen-SOJMVxIq.js +0 -2
  65. package/dist/hub/assets/main-Bjq_U0cU.js +0 -2
  66. package/dist/hub/assets/workflow-CnSY-W41.js +0 -1
@@ -53,7 +53,7 @@ import {
53
53
  vendoredPath,
54
54
  whereUsed,
55
55
  withFile
56
- } from "./chunk-O66KB7BU.js";
56
+ } from "./chunk-3HON5Q5K.js";
57
57
  import {
58
58
  escapingLinks,
59
59
  within
@@ -67,7 +67,7 @@ import {
67
67
  libraryOfPackage,
68
68
  packageOf,
69
69
  playwrightCli
70
- } from "./chunk-7P4UXAIY.js";
70
+ } from "./chunk-HDJ2TOWZ.js";
71
71
  import {
72
72
  MissingIndexError,
73
73
  buildGaps,
@@ -91,7 +91,7 @@ import {
91
91
  showFromCatalog,
92
92
  storeLocation,
93
93
  syncIndex
94
- } from "./chunk-3SQQNQDN.js";
94
+ } from "./chunk-6GITMASZ.js";
95
95
  import {
96
96
  DL_EXT,
97
97
  buildTokens,
@@ -101,7 +101,7 @@ import {
101
101
  parseCssColor,
102
102
  parseDimension,
103
103
  readRules
104
- } from "./chunk-TV5UX3FE.js";
104
+ } from "./chunk-FLBRX6Y3.js";
105
105
  import {
106
106
  Baseline,
107
107
  DESIGN_CONFIG_FILE,
@@ -115,6 +115,8 @@ import {
115
115
  PACKAGE_NAME,
116
116
  ProjectConfig,
117
117
  ScanReport,
118
+ WORKSPACE_FILE,
119
+ WorkspaceConfig,
118
120
  copyleft,
119
121
  executionLabel,
120
122
  findFiles,
@@ -136,7 +138,7 @@ import {
136
138
  shortHash,
137
139
  toPosix,
138
140
  writeFileAtomic
139
- } from "./chunk-YWBQO7PO.js";
141
+ } from "./chunk-DWYDHVLZ.js";
140
142
  import {
141
143
  __toESM
142
144
  } from "./chunk-WNTS7ZO4.js";
@@ -146,7 +148,7 @@ var import_yaml4 = __toESM(require_dist(), 1);
146
148
  import { execFile as execFile5 } from "node:child_process";
147
149
  import { existsSync as existsSync5 } from "node:fs";
148
150
  import { appendFile as appendFile2, readFile as readFile10, rm as rm6, rmdir as rmdir3 } from "node:fs/promises";
149
- import { basename as basename5, dirname as dirname12, join as join24, relative as relative10, resolve as resolve14 } from "node:path";
151
+ import { basename as basename5, dirname as dirname13, join as join25, relative as relative11, resolve as resolve15 } from "node:path";
150
152
  import { parseArgs, promisify as promisify5 } from "node:util";
151
153
 
152
154
  // ../cli/src/check.ts
@@ -164,7 +166,7 @@ import { join as join2, relative, resolve } from "node:path";
164
166
 
165
167
  // ../cli/src/command.ts
166
168
  var COMMAND = "youiyoux";
167
- var SUBCOMMANDS = ["show", "where", "bom", "check", "baseline", "rules", "plan", "migrate", "init", "adopt", "system", "sync", "link", "unlink", "scan", "watch", "hooks", "agents", "mcp", "ui", "library", "discover", "index", "report", "render", "screens", "requests", "detect", "build", "parity", "schema", "inventory", "gaps", "help"];
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"];
168
170
 
169
171
  // ../cli/src/agents.ts
170
172
  var import_yaml = __toESM(require_dist(), 1);
@@ -1058,7 +1060,7 @@ async function runCheck(project2, options = {}) {
1058
1060
  const { report } = scan;
1059
1061
  const checked = new Set(scan.files);
1060
1062
  const unmatched = scope ? [...scope].filter((f) => !checked.has(f)) : [];
1061
- const failed = report.coverage.failed.filter((f) => !scope || scope.has(f.file) || !/\.(tsx?|css)$/.test(f.file));
1063
+ const failed2 = report.coverage.failed.filter((f) => !scope || scope.has(f.file) || !/\.(tsx?|css)$/.test(f.file));
1062
1064
  const wantedRule = (id) => !options.rule || id.endsWith(`/rule/${options.rule}`);
1063
1065
  const violations = report.violations.filter((v) => wantedRule(v.rule) && (!options.quiet || v.severity === "error"));
1064
1066
  const notRun = failedChecks(report.checks).filter((c) => wantedRule(c.rule));
@@ -1069,7 +1071,7 @@ async function runCheck(project2, options = {}) {
1069
1071
  const failing = baseline ? [...baseline.comparison.new, ...baseline.comparison.regressed] : violations;
1070
1072
  const errors = failing.filter((v) => v.severity === "error").length + (lock ?? []).filter((i) => i.severity === "error").length;
1071
1073
  const drift = diff ? await analyseChange(project2, scan, diff, { violations }) : null;
1072
- return { identity: scan.identity, scan, scope, unmatched, failed, notRun, violations, lock, baseline, errors, incomplete: unmatched.length > 0 || failed.length > 0 || notRun.length > 0 || (drift?.incomplete.length ?? 0) > 0, diff: drift };
1074
+ return { identity: scan.identity, scan, scope, unmatched, failed: failed2, notRun, violations, lock, baseline, errors, incomplete: unmatched.length > 0 || failed2.length > 0 || notRun.length > 0 || (drift?.incomplete.length ?? 0) > 0, diff: drift };
1073
1075
  }
1074
1076
  async function lockIssues(project2) {
1075
1077
  const lock = await verifyLock(project2);
@@ -1779,18 +1781,18 @@ async function runClaudeHook(input, target = {}) {
1779
1781
  try {
1780
1782
  const project2 = await load(target, dirname5(file));
1781
1783
  const real = (path) => realpath3(path).catch(() => path);
1782
- const relative11 = relPath(await real(project2.root), await real(file));
1783
- if (!isChecked(project2, relative11)) return SILENT;
1784
- const found = await changeFor(() => workingTreeChange(project2, void 0, [relative11]));
1784
+ const relative12 = relPath(await real(project2.root), await real(file));
1785
+ if (!isChecked(project2, relative12)) return SILENT;
1786
+ const found = await changeFor(() => workingTreeChange(project2, void 0, [relative12]));
1785
1787
  if (found.problem !== void 0) return claudeContext(found.problem, project2.root);
1786
1788
  const { change } = found;
1787
1789
  const result = configured(project2) ? await runCheck(project2, { files: [file], lock: false, baseline: await baselineFor(project2, target), diff: change }) : await runRepoCheck(project2, change);
1788
1790
  const lines = findingLines(result, project2.root);
1789
- const see = COMPONENT_FILE.test(relative11) ? `See it: youiyoux render ${quoted(relative11)} (or the MCP tool ui_render), then open the images: light and dark, desktop and phone, accessibility issues and the diff against the base.` : null;
1790
- if (lines.length === 0) return see ? claudeContext(`youiyoux: ${relative11} passes the design-system check. ${see}`, project2.root) : SILENT;
1791
+ const see = COMPONENT_FILE.test(relative12) ? `See it: youiyoux render ${quoted(relative12)} (or the MCP tool ui_render), then open the images: light and dark, desktop and phone, accessibility issues and the diff against the base.` : null;
1792
+ if (lines.length === 0) return see ? claudeContext(`youiyoux: ${relative12} passes the design-system check. ${see}`, project2.root) : SILENT;
1791
1793
  const older = "violations" in result ? result.violations.filter((v) => !isAdded(change.added, v.file, v.line)).length : 0;
1792
1794
  const known = older > 0 ? ` (${older} older findings on unchanged lines omitted)` : "";
1793
- return claudeContext(`youiyoux design-system check (advisory) on ${relative11}${known}:
1795
+ return claudeContext(`youiyoux design-system check (advisory) on ${relative12}${known}:
1794
1796
  ${lines.join("\n")}${!configured(project2) ? `
1795
1797
  ${result.diff?.notes.join("\n")}` : ""}
1796
1798
  Fix these before finishing (each "Fix:" says what to write); \`youiyoux show <component>\` and the youiyoux MCP tools give the legal values. CI runs the authoritative check.${see ? `
@@ -2085,7 +2087,7 @@ import { homedir, userInfo } from "node:os";
2085
2087
  import { join as join12, resolve as resolve6 } from "node:path";
2086
2088
  async function swapImpact(candidate, family) {
2087
2089
  try {
2088
- const { discoverIndexPath: discoverIndexPath2, sharedStore: sharedStore2 } = await import("./src-DYZIE4XZ.js");
2090
+ const { discoverIndexPath: discoverIndexPath2, sharedStore: sharedStore2 } = await import("./src-DPFJ4S2N.js");
2089
2091
  const path = discoverIndexPath2();
2090
2092
  if (!process.env.DATABASE_URL && !existsSync(path)) return null;
2091
2093
  const impact = await (await sharedStore2(path, process.env, { readOnly: true })).swapImpact(candidate, family);
@@ -2096,7 +2098,7 @@ async function swapImpact(candidate, family) {
2096
2098
  }
2097
2099
  async function libraryLicence(id) {
2098
2100
  try {
2099
- const { discoverCacheDir: discoverCacheDir2, findListing } = await import("./src-DYZIE4XZ.js");
2101
+ const { discoverCacheDir: discoverCacheDir2, findListing } = await import("./src-DPFJ4S2N.js");
2100
2102
  const { entry } = await findListing(discoverCacheDir2(void 0, process.env), id);
2101
2103
  return entry.id === id ? entry.license : null;
2102
2104
  } catch {
@@ -2104,7 +2106,7 @@ async function libraryLicence(id) {
2104
2106
  }
2105
2107
  }
2106
2108
  async function startRuleEditor(options) {
2107
- const { FileStore, RuleWorkflow, serveWorkflow } = await import("./src-4JGIPP5A.js");
2109
+ const { FileStore, RuleWorkflow, serveWorkflow } = await import("./src-EUVBYTKY.js");
2108
2110
  const projectRoot = resolve6(options.project);
2109
2111
  const load2 = { ...options.config ? { configPath: resolve6(options.config) } : {}, ...options.design ? { designRoot: resolve6(options.design) } : {}, ...options.root ? { productRoot: resolve6(options.root) } : {} };
2110
2112
  const project2 = await loadProject(projectRoot, load2);
@@ -2145,7 +2147,7 @@ function builtHubPlan(toolRoot, options, out) {
2145
2147
  if (options.watch && !namesSystem(options)) throw new Error("--watch keeps a system's snapshot live: name it with --design or --project (the demo system is not watched)");
2146
2148
  const hub = join13(toolRoot, BUILT_HUB);
2147
2149
  const snapshot = flags.length > 0 ? [join13(toolRoot, "hub-snapshot.js"), "--out", out, ...flags] : null;
2148
- const server = [join13(toolRoot, "hub-server.js"), "--dist", hub, "--kit", join13(hub, "kit"), "--snapshot", snapshot ? out : join13(toolRoot, BUILT_DEMO), ...snapshot ? ["--build-frame"] : [], ...options.port ? ["--port", options.port] : [], ...options.api ? ["--api", options.api] : [], ...options.watch ? ["--live"] : []];
2150
+ const server = [join13(toolRoot, "hub-server.js"), "--dist", hub, "--kit", join13(hub, "kit"), "--snapshot", snapshot ? out : join13(toolRoot, BUILT_DEMO), ...snapshot ? ["--build-frame"] : [], ...options.port ? ["--port", options.port] : [], ...options.api ? ["--api", options.api] : [], ...options.watch || options.workspace ? ["--live"] : []];
2149
2151
  return { snapshot, server, watch: options.watch && snapshot ? [...snapshot, "--watch"] : null };
2150
2152
  }
2151
2153
  function run5(args, cwd, env, started) {
@@ -2170,6 +2172,7 @@ async function runBuiltHub(toolRoot, options) {
2170
2172
  const code = await run5(plan.snapshot, process.cwd(), {}, (child) => children.add(child));
2171
2173
  if (code !== 0) return code;
2172
2174
  }
2175
+ options.workspace?.((project2) => run5(builtHubPlan(toolRoot, { ...options, project: project2 }, out).snapshot, process.cwd(), {}, (child) => children.add(child)));
2173
2176
  if (plan.watch) children.add(spawn(process.execPath, plan.watch, { cwd: process.cwd(), stdio: "inherit" }));
2174
2177
  return await run5(plan.server, process.cwd(), {}, (child) => children.add(child));
2175
2178
  } finally {
@@ -2189,6 +2192,7 @@ async function runHub(toolRoot, options) {
2189
2192
  const code = await run5(plan.snapshot, process.cwd(), {});
2190
2193
  if (code !== 0) return code;
2191
2194
  }
2195
+ options.workspace?.((project2) => run5(hubPlan(toolRoot, { ...options, project: project2 }).snapshot, process.cwd(), {}));
2192
2196
  const watcher = plan.watch ? spawn(process.execPath, plan.watch, { cwd: process.cwd(), stdio: "inherit" }) : null;
2193
2197
  try {
2194
2198
  return await run5(plan.vite, plan.web, plan.env);
@@ -2630,15 +2634,193 @@ async function extractSystem(project2, dir, options = {}) {
2630
2634
  }
2631
2635
  }
2632
2636
 
2637
+ // ../cli/src/status.ts
2638
+ import { realpath as realpath5 } from "node:fs/promises";
2639
+ import { dirname as dirname9, join as join16, relative as relative8, resolve as resolve10 } from "node:path";
2640
+ var placeOf = (cwd, root) => {
2641
+ const rel = relative8(cwd, root) || ".";
2642
+ return rel.split(/[\\/]/).filter((part) => part === "..").length > 1 ? resolve10(root) : rel;
2643
+ };
2644
+ var WRITES = /* @__PURE__ */ new Set(["created", "updated", "merged", "adopted", "conflict", "removed"]);
2645
+ function sourceOf(project2) {
2646
+ if (project2.linked) return `your checkout ${project2.linked}`;
2647
+ const source = project2.config.source;
2648
+ if ("package" in source) return `package ${source.package}`;
2649
+ if ("git" in source) return `git ${source.git} at ${source.ref}`;
2650
+ return resolve10(project2.root) === resolve10(project2.repo.root) ? "this repo" : `path ${source.path}`;
2651
+ }
2652
+ function nextStep(s) {
2653
+ if (s.sync.state === "never") return "youiyoux sync: this product has never been synced with its System";
2654
+ if (s.sync.state === "conflict") return "youiyoux sync: resolve the conflicts it reports, then youiyoux sync --adopt records them";
2655
+ if (s.sync.state === "behind") return `youiyoux sync: ${plural(s.sync.changes.length, "file")} would change`;
2656
+ if (s.check.incomplete) return "youiyoux check: some files or rules could not be checked, and it says which";
2657
+ if (s.check.errors > 0) return `youiyoux check: fix ${plural(s.check.errors, "error")}`;
2658
+ if (s.requests.open > 0) return `youiyoux requests: answer ${plural(s.requests.open, "open request")}`;
2659
+ if (s.check.warnings > 0 && !s.check.baseline) return `youiyoux check: ${plural(s.check.warnings, "warning")} to fix, or youiyoux baseline records them as accepted debt`;
2660
+ return "nothing to do";
2661
+ }
2662
+ async function projectStatus(project2, cwd = process.cwd()) {
2663
+ const lock = await readLock(project2.root);
2664
+ const { actions } = await syncProject(project2, { dryRun: true });
2665
+ const changes = actions.filter((a) => WRITES.has(a.action)).map((a) => ({ file: a.file, action: a.action }));
2666
+ const baselineFile2 = baselinePath(project2);
2667
+ const check = await runCheck(project2, { baseline: await readTextOrNull(baselineFile2) === null ? null : baselineFile2 });
2668
+ const comparison = check.baseline?.comparison;
2669
+ const counted = comparison ? [...comparison.new, ...comparison.regressed] : check.violations;
2670
+ const usages = check.scan.report.usages;
2671
+ const { RequestStore } = await import("./src-EUVBYTKY.js");
2672
+ const requests = await new RequestStore(project2.root, project2.config.id).list();
2673
+ const status = {
2674
+ id: project2.config.id,
2675
+ root: placeOf(cwd, project2.root),
2676
+ system: { id: project2.system.config.id, name: project2.system.config.name, version: project2.system.config.version, source: sourceOf(project2), linked: Boolean(project2.linked), commit: project2.designCommit ?? null },
2677
+ lock: lock ? { systemVersion: lock.systemVersion, syncedAt: lock.syncedAt } : null,
2678
+ sync: { state: lock === null ? "never" : actions.some((a) => a.action === "conflict") ? "conflict" : changes.length > 0 ? "behind" : "current", changes },
2679
+ drift: (await verifyLock(project2) ?? []).map((i) => ({ file: i.file, severity: i.severity, message: i.message })),
2680
+ check: {
2681
+ errors: check.errors,
2682
+ warnings: counted.filter((v) => v.severity === "warn").length,
2683
+ baseline: comparison ? { known: comparison.known.length, new: comparison.new.length + comparison.regressed.length, fixed: comparison.fixed.reduce((n, f) => n + f.gone, 0) } : null,
2684
+ incomplete: check.incomplete
2685
+ },
2686
+ components: { system: project2.system.components.length, used: new Set(usages.map((u) => u.element)).size, sites: usages.length },
2687
+ requests: { open: requests.requests.filter((r) => r.status === "open").length, addressed: requests.requests.filter((r) => r.status === "addressed").length, unreadable: requests.unreadable.length }
2688
+ };
2689
+ return { ...status, next: nextStep(status) };
2690
+ }
2691
+ async function statusTargets(cwd, named2) {
2692
+ if (named2) return { roots: [resolve10(named2)], workspace: null };
2693
+ const product2 = findUp(cwd, PROJECT_FILE);
2694
+ if (product2) return { roots: [product2], workspace: null };
2695
+ const at = findUp(cwd, WORKSPACE_FILE);
2696
+ if (at) {
2697
+ const file = join16(at, WORKSPACE_FILE);
2698
+ const workspace = await readDefinition(file, WorkspaceConfig);
2699
+ return { roots: workspace.projects.map((p) => resolve10(at, p)), workspace: file };
2700
+ }
2701
+ const top = findUp(cwd, ".git") ?? null;
2702
+ if (top === null) return { roots: [], workspace: null };
2703
+ const configs = await findFiles(cwd, [`**/${PROJECT_FILE}`]);
2704
+ const roots = [];
2705
+ for (const config of configs) {
2706
+ const dir = resolve10(cwd, dirname9(config));
2707
+ if (await realpath5(findUp(dir, ".git") ?? dir) === await realpath5(top)) roots.push(dir);
2708
+ }
2709
+ return { roots, workspace: null };
2710
+ }
2711
+ async function workspaceStatus(cwd, named2) {
2712
+ const { roots, workspace } = await statusTargets(cwd, named2);
2713
+ const projects = [];
2714
+ for (const root of roots) {
2715
+ try {
2716
+ projects.push(await projectStatus(await loadProject(root), cwd));
2717
+ } catch (error) {
2718
+ const label = placeOf(cwd, root);
2719
+ 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)}` });
2720
+ }
2721
+ }
2722
+ return { schema: "youi.status/v1", generatedAt: (/* @__PURE__ */ new Date()).toISOString(), workspace: workspace ? relative8(cwd, workspace) || WORKSPACE_FILE : null, projects };
2723
+ }
2724
+ var failed = (p) => "error" in p;
2725
+ function projectLines(s) {
2726
+ const row = (label, text) => ` ${padEnd(label, 11)} ${text}`;
2727
+ const synced = s.lock ? `synced ${s.lock.syncedAt.slice(0, 10)}${s.lock.systemVersion !== s.system.version ? ` at v${s.lock.systemVersion}` : ""}` : "never synced";
2728
+ const sync = { current: style.ok("up to date"), behind: style.warn(`behind: ${plural(s.sync.changes.length, "file")} would change`), conflict: style.error(`conflict: ${plural(s.sync.changes.filter((c) => c.action === "conflict").length, "file")}`), never: style.warn("never synced") }[s.sync.state];
2729
+ const edited = s.drift.filter((d) => d.severity === "warn");
2730
+ const broken = s.drift.filter((d) => d.severity === "error");
2731
+ const drift = s.drift.length === 0 ? style.ok("none") : [broken.length > 0 ? style.error(`${plural(broken.length, "file")} wrong (${broken.slice(0, 3).map((d) => d.file.split("/").at(-1)).join(", ")})`) : "", edited.length > 0 ? style.warn(`${plural(edited.length, "owned file")} edited locally, merged on sync (${edited.slice(0, 3).map((d) => d.file.split("/").at(-1)).join(", ")})`) : ""].filter(Boolean).join("; ");
2732
+ const { check } = s;
2733
+ const counts = `${check.errors > 0 ? style.error(plural(check.errors, "error")) : style.ok("0 errors")} \xB7 ${plural(check.warnings, "warning")}`;
2734
+ const baseline = check.baseline ? style.dim(` beyond the baseline (${check.baseline.known} accepted${check.baseline.fixed > 0 ? `, ${check.baseline.fixed} fixed` : ""})`) : "";
2735
+ return [
2736
+ `${style.bold(s.id)}${s.root === s.id ? "" : ` ${style.dim(`\xB7 ${s.root}`)}`} \xB7 ${s.system.name} v${s.system.version} ${style.dim(`(${s.system.source}${s.system.linked ? ", linked" : ""}) \xB7 ${synced}`)}`,
2737
+ row("sync", sync),
2738
+ row("drift", drift),
2739
+ row("check", `${counts}${baseline}${check.incomplete ? style.warn(" \xB7 incomplete: not a pass") : ""}`),
2740
+ row("components", `${s.components.used} of ${s.components.system} System components used, at ${plural(s.components.sites, "site")}`),
2741
+ row("requests", s.requests.open + s.requests.addressed + s.requests.unreadable === 0 ? style.dim("none") : [s.requests.open > 0 ? style.warn(`${s.requests.open} open`) : "0 open", `${s.requests.addressed} addressed`, ...s.requests.unreadable > 0 ? [style.error(`${s.requests.unreadable} unreadable`)] : []].join(" \xB7 ")),
2742
+ `${style.bold("Next:")} ${s.next}`
2743
+ ];
2744
+ }
2745
+ function renderStatus(report) {
2746
+ if (report.projects.length === 0) return `${style.warn("!")} no product here: no ${PROJECT_FILE} upward, no ${WORKSPACE_FILE}, and none in this repository below here
2747
+ Next: youiyoux adopt makes this product's own UI its design system, or youiyoux init --design <dir> follows one`;
2748
+ const blocks = report.projects.map((p) => failed(p) ? [`${style.bold(p.root)} ${style.error("\u2716")} ${p.error}`, `${style.bold("Next:")} ${p.next}`] : projectLines(p));
2749
+ const head = report.projects.length > 1 ? [`${style.bold("workspace")} ${style.dim(`\xB7 ${plural(report.projects.length, "product")}${report.workspace ? ` from ${report.workspace}` : " in this repository"}`)}`, ""] : [];
2750
+ return [...head, ...blocks.flatMap((b, i) => i === 0 ? b : ["", ...b])].join("\n");
2751
+ }
2752
+ var statusExitCode = (report) => report.projects.some((p) => failed(p) || p.check.incomplete || p.check.errors > 0 || p.sync.state === "conflict") ? 1 : 0;
2753
+
2754
+ // ../cli/src/workspace-hub.ts
2755
+ import { randomBytes as randomBytes2 } from "node:crypto";
2756
+ import { createServer } from "node:http";
2757
+ var KEY_HEADER = "x-youi-session";
2758
+ function send(res, status, body) {
2759
+ res.writeHead(status, { "Content-Type": "application/json", "Cache-Control": "no-store" });
2760
+ res.end(JSON.stringify(body));
2761
+ }
2762
+ async function readBody(req) {
2763
+ let text = "";
2764
+ for await (const chunk2 of req) {
2765
+ text += String(chunk2);
2766
+ if (text.length > 4096) throw new Error("request too large");
2767
+ }
2768
+ return text ? JSON.parse(text) : {};
2769
+ }
2770
+ async function startWorkspaceHub(options) {
2771
+ const key2 = randomBytes2(18).toString("base64url");
2772
+ let report = await options.status();
2773
+ let current = options.current;
2774
+ let busy = false;
2775
+ const server = createServer((req, res) => {
2776
+ void (async () => {
2777
+ const path = (req.url ?? "").split("?")[0];
2778
+ if (req.method === "GET" && path === "/api/workspace") return send(res, 200, { report, current });
2779
+ if (req.method !== "POST" || path !== "/api/workspace/open" && path !== "/api/workspace/refresh") {
2780
+ return send(res, 404, { error: "Not in a workspace hub: Rules and Changes are read-only here; youiyoux ui --project <dir> opens the rule editor on one product" });
2781
+ }
2782
+ if (req.headers[KEY_HEADER] !== key2) return send(res, 401, { error: "this tab does not carry this run's key" });
2783
+ if (busy) return send(res, 409, { error: "another product is opening; try again in a moment" });
2784
+ busy = true;
2785
+ try {
2786
+ if (path === "/api/workspace/refresh") {
2787
+ report = await options.status();
2788
+ return send(res, 200, { report, current });
2789
+ }
2790
+ const { index } = await readBody(req);
2791
+ const entry = typeof index === "number" && Number.isInteger(index) ? report.projects[index] : void 0;
2792
+ if (entry === void 0 || options.roots[index] === void 0) return send(res, 400, { error: `no product ${JSON.stringify(index)} in this workspace` });
2793
+ if ("error" in entry) return send(res, 400, { error: `${entry.root} cannot be opened: ${entry.error}`, problems: [entry.next] });
2794
+ const code = await options.open(options.roots[index]);
2795
+ if (code !== 0) return send(res, 500, { error: `the snapshot of ${entry.root} failed (exit ${code}); the hub still shows the product it showed` });
2796
+ current = index;
2797
+ return send(res, 200, { report, current });
2798
+ } catch (error) {
2799
+ return send(res, 400, { error: error instanceof Error ? error.message : String(error) });
2800
+ } finally {
2801
+ busy = false;
2802
+ }
2803
+ })();
2804
+ });
2805
+ await new Promise((done) => server.listen(0, "127.0.0.1", done));
2806
+ const address = server.address();
2807
+ const port = typeof address === "object" && address ? address.port : 0;
2808
+ return {
2809
+ url: `http://127.0.0.1:${port}`,
2810
+ key: key2,
2811
+ close: () => new Promise((done) => server.close(() => done()))
2812
+ };
2813
+ }
2814
+
2633
2815
  // ../cli/src/index-store.ts
2634
2816
  import { appendFile, mkdir as mkdir4, readFile as readFile6, stat as stat2, rename as rename2, mkdtemp as mkdtemp4, rm as rm5 } from "node:fs/promises";
2635
- import { dirname as dirname9, join as join16, resolve as resolve10 } from "node:path";
2817
+ import { dirname as dirname10, join as join17, resolve as resolve11 } from "node:path";
2636
2818
  var SOURCES_FILE = "index-sources.json";
2637
2819
  var SCANS_LOG = "scans.jsonl";
2638
2820
  var EMPTY = { discover: null, inventories: [], projects: [] };
2639
2821
  async function readIndexSources(home) {
2640
2822
  try {
2641
- const raw = JSON.parse(await readFile6(join16(home, SOURCES_FILE), "utf8"));
2823
+ const raw = JSON.parse(await readFile6(join17(home, SOURCES_FILE), "utf8"));
2642
2824
  return { discover: raw.discover ?? null, inventories: raw.inventories ?? [], projects: raw.projects ?? [] };
2643
2825
  } catch {
2644
2826
  return EMPTY;
@@ -2651,14 +2833,14 @@ async function noteSource(home, change) {
2651
2833
  inventories: change.inventory && !sources.inventories.includes(change.inventory) ? [...sources.inventories, change.inventory] : sources.inventories,
2652
2834
  projects: change.project ? [...sources.projects.filter((p) => p.root !== change.project.root), change.project] : sources.projects
2653
2835
  };
2654
- await writeFileAtomic(join16(home, SOURCES_FILE), `${JSON.stringify(next2, null, 2)}
2836
+ await writeFileAtomic(join17(home, SOURCES_FILE), `${JSON.stringify(next2, null, 2)}
2655
2837
  `);
2656
2838
  }
2657
2839
  async function recordInventory(store, home, report, file) {
2658
- const run7 = inventoryRun(report, resolve10(file));
2840
+ const run7 = inventoryRun(report, resolve11(file));
2659
2841
  const logged = { run: run7.run, source: run7.source, scannedAt: run7.scannedAt, projects: run7.projects, families: run7.families };
2660
2842
  await mkdir4(home, { recursive: true });
2661
- await appendFile(join16(home, SCANS_LOG), `${JSON.stringify({ schema: "youi.scan-log/v1", ...logged })}
2843
+ await appendFile(join17(home, SCANS_LOG), `${JSON.stringify({ schema: "youi.scan-log/v1", ...logged })}
2662
2844
  `);
2663
2845
  await store.recordInventory(run7);
2664
2846
  await noteSource(home, { inventory: run7.source });
@@ -2669,7 +2851,7 @@ async function recordProject(store, project2, usage) {
2669
2851
  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 }));
2670
2852
  }
2671
2853
  async function readLog(home) {
2672
- const text = await readFile6(join16(home, SCANS_LOG), "utf8").catch(() => "");
2854
+ const text = await readFile6(join17(home, SCANS_LOG), "utf8").catch(() => "");
2673
2855
  return text.split("\n").flatMap((line) => {
2674
2856
  if (!line.trim()) return [];
2675
2857
  try {
@@ -2684,9 +2866,9 @@ async function rebuildIndex(path, options = {}) {
2684
2866
  const started = performance.now();
2685
2867
  const env = options.env ?? process.env;
2686
2868
  const home = indexHome(path, env);
2687
- await mkdir4(dirname9(path), { recursive: true });
2869
+ await mkdir4(dirname10(path), { recursive: true });
2688
2870
  const scratch = !env.DATABASE_URL ? await mkdtemp4(`${path}.rebuild-`) : null;
2689
- const target = scratch ? join16(scratch, "index.db") : path;
2871
+ const target = scratch ? join17(scratch, "index.db") : path;
2690
2872
  const store = scratch ? await openSqlite(target) : await sharedStore(path, env);
2691
2873
  try {
2692
2874
  if (env.DATABASE_URL) await store.reset();
@@ -2694,7 +2876,7 @@ async function rebuildIndex(path, options = {}) {
2694
2876
  const sources = await readIndexSources(home);
2695
2877
  const cache = options.discoverCache ?? sources.discover;
2696
2878
  let discover = { cache, chosen: 0, all: 0 };
2697
- if (cache && await stat2(join16(cache, "index.json")).then(() => true, () => false)) {
2879
+ if (cache && await stat2(join17(cache, "index.json")).then(() => true, () => false)) {
2698
2880
  const loaded = await ingestCatalog(store, cache);
2699
2881
  discover = { cache, chosen: loaded.chosen, all: loaded.all };
2700
2882
  }
@@ -2711,25 +2893,25 @@ async function rebuildIndex(path, options = {}) {
2711
2893
  await store.recordInventory(inventoryRun(parsed.data, file));
2712
2894
  replayed++;
2713
2895
  }
2714
- const failed = [];
2896
+ const failed2 = [];
2715
2897
  let projects = 0;
2716
2898
  const gone = [];
2717
2899
  for (const source of sources.projects) {
2718
2900
  if (!await stat2(source.root).then((s) => s.isDirectory(), () => false)) {
2719
2901
  gone.push(source.root);
2720
- failed.push({ root: source.root, reason: "folder not found (moved or deleted), skipped" });
2902
+ failed2.push({ root: source.root, reason: "folder not found (moved or deleted), skipped" });
2721
2903
  continue;
2722
2904
  }
2723
2905
  try {
2724
2906
  const project2 = await loadProject(source.root, source.options);
2725
- const usage = ScanReport.safeParse(await readJson(source.usage ?? join16(project2.root, ".youi/usage.json")));
2907
+ const usage = ScanReport.safeParse(await readJson(source.usage ?? join17(project2.root, ".youi/usage.json")));
2726
2908
  await recordProject(store, project2, usage.success ? usage.data : null);
2727
2909
  projects++;
2728
2910
  } catch (error) {
2729
- failed.push({ root: source.root, reason: error instanceof Error ? error.message.split("\n")[0] : String(error) });
2911
+ failed2.push({ root: source.root, reason: error instanceof Error ? error.message.split("\n")[0] : String(error) });
2730
2912
  }
2731
2913
  }
2732
- const broken = failed.filter((f) => !gone.includes(f.root));
2914
+ const broken = failed2.filter((f) => !gone.includes(f.root));
2733
2915
  if (broken.length) throw new Error(`Index rebuild failed: ${broken.map((f) => `${f.root}: ${f.reason}`).join("; ")}`);
2734
2916
  await linkCandidates(store);
2735
2917
  const tables = (await store.stats()).tables;
@@ -2753,7 +2935,7 @@ async function rebuildIndex(path, options = {}) {
2753
2935
  throw error;
2754
2936
  }
2755
2937
  }
2756
- return { location: scratch ? path : store.location, discover, scans: log.length, inventories: { replayed, missing }, projects: { replayed: projects, failed }, tables, durationMs: Math.round(performance.now() - started) };
2938
+ return { location: scratch ? path : store.location, discover, scans: log.length, inventories: { replayed, missing }, projects: { replayed: projects, failed: failed2 }, tables, durationMs: Math.round(performance.now() - started) };
2757
2939
  } finally {
2758
2940
  if (scratch) {
2759
2941
  await store.close();
@@ -2939,9 +3121,9 @@ function renderAdoptionRequest(request) {
2939
3121
  }
2940
3122
 
2941
3123
  // ../cli/src/report/run.ts
2942
- import { randomBytes as randomBytes2 } from "node:crypto";
3124
+ import { randomBytes as randomBytes3 } from "node:crypto";
2943
3125
  import { mkdir as mkdir5, rename as rename3, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
2944
- import { join as join23, relative as relative9, resolve as resolve13 } from "node:path";
3126
+ import { join as join24, relative as relative10, resolve as resolve14 } from "node:path";
2945
3127
 
2946
3128
  // ../cli/src/report/card.ts
2947
3129
  import { deflateSync } from "node:zlib";
@@ -3177,7 +3359,7 @@ function drawCard(input) {
3177
3359
 
3178
3360
  // ../cli/src/report/model.ts
3179
3361
  import { readFile as readFile8 } from "node:fs/promises";
3180
- import { join as join20 } from "node:path";
3362
+ import { join as join21 } from "node:path";
3181
3363
 
3182
3364
  // ../cli/src/report/filters.ts
3183
3365
  var SHOWCASE_GLOBS = ["**/{__stories__,.storybook,storybook,storybook-static,example,examples,demo,demos,playground,showcase,showcases}/**", "**/*.stories.*", "**/*.story.*"];
@@ -3304,11 +3486,11 @@ function publicLook(caption) {
3304
3486
 
3305
3487
  // ../cli/src/report/groups.ts
3306
3488
  import { existsSync as existsSync3 } from "node:fs";
3307
- import { join as join18 } from "node:path";
3489
+ import { join as join19 } from "node:path";
3308
3490
 
3309
3491
  // ../cli/src/report/imports.ts
3310
3492
  import { realpathSync } from "node:fs";
3311
- import { dirname as dirname10, join as join17, relative as relative8, resolve as resolve11 } from "node:path";
3493
+ import { dirname as dirname11, join as join18, relative as relative9, resolve as resolve12 } from "node:path";
3312
3494
  import ts from "typescript";
3313
3495
  var resolvers = /* @__PURE__ */ new Map();
3314
3496
  function resolverOf(root) {
@@ -3316,7 +3498,7 @@ function resolverOf(root) {
3316
3498
  if (!found) {
3317
3499
  const config = ts.findConfigFile(root, ts.sys.fileExists, "tsconfig.json") ?? ts.findConfigFile(root, ts.sys.fileExists, "jsconfig.json");
3318
3500
  const read = config ? ts.readConfigFile(config, ts.sys.readFile) : null;
3319
- const options = config && read && !read.error ? ts.parseJsonConfigFileContent(read.config, ts.sys, dirname10(config)).options : {};
3501
+ const options = config && read && !read.error ? ts.parseJsonConfigFileContent(read.config, ts.sys, dirname11(config)).options : {};
3320
3502
  found = { options, cache: ts.createModuleResolutionCache(root, (name) => name, options) };
3321
3503
  resolvers.set(root, found);
3322
3504
  }
@@ -3327,13 +3509,13 @@ function clearImportCache() {
3327
3509
  }
3328
3510
  async function verifiedImport(root, keeper, from, suggested) {
3329
3511
  const { options, cache } = resolverOf(root);
3330
- let local = relative8(dirname10(join17(root, from)), join17(root, keeper)).replaceAll("\\", "/").replace(/\.(tsx?|jsx?|mjs)$/, "");
3512
+ let local = relative9(dirname11(join18(root, from)), join18(root, keeper)).replaceAll("\\", "/").replace(/\.(tsx?|jsx?|mjs)$/, "");
3331
3513
  if (!local.startsWith(".")) local = `./${local}`;
3332
3514
  for (const specifier of /* @__PURE__ */ new Set([suggested, local])) {
3333
- const found = ts.resolveModuleName(specifier, resolve11(root, from), options, ts.sys, cache).resolvedModule?.resolvedFileName;
3515
+ const found = ts.resolveModuleName(specifier, resolve12(root, from), options, ts.sys, cache).resolvedModule?.resolvedFileName;
3334
3516
  if (found) {
3335
3517
  try {
3336
- if (realpathSync(found) === realpathSync(join17(root, keeper))) return specifier;
3518
+ if (realpathSync(found) === realpathSync(join18(root, keeper))) return specifier;
3337
3519
  } catch {
3338
3520
  }
3339
3521
  }
@@ -3741,7 +3923,7 @@ function factsOf(project2, id, modules, eligible, workspaceNames, dependencies,
3741
3923
  if (dirs.has(file.slice(0, at))) break;
3742
3924
  dirs.add(file.slice(0, at));
3743
3925
  }
3744
- const roots = [...dirs].filter((dir) => existsSync3(join18(project2.root, dir, "package.json"))).sort((a, b) => b.length - a.length);
3926
+ const roots = [...dirs].filter((dir) => existsSync3(join19(project2.root, dir, "package.json"))).sort((a, b) => b.length - a.length);
3745
3927
  const nested = (file) => roots.find((dir) => file.startsWith(`${dir}/`)) ?? "";
3746
3928
  return { project: project2, id, dependencies, packageImports, jsxCounts, eligible, twins, dirs, importer, packageOf: nested };
3747
3929
  }
@@ -3749,11 +3931,11 @@ function factsOf(project2, id, modules, eligible, workspaceNames, dependencies,
3749
3931
  // ../cli/src/report/projects.ts
3750
3932
  var import_yaml3 = __toESM(require_dist(), 1);
3751
3933
  import { readFile as readFile7 } from "node:fs/promises";
3752
- import { basename as basename4, join as join19, resolve as resolve12 } from "node:path";
3934
+ import { basename as basename4, join as join20, resolve as resolve13 } from "node:path";
3753
3935
  var UI_FILES = ["**/*.{tsx,jsx,astro,vue,svelte}"];
3754
3936
  var strings = (value) => Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
3755
3937
  async function workspaceGlobs(root, pkg) {
3756
- const pnpm = await readFile7(join19(root, "pnpm-workspace.yaml"), "utf8").catch(() => null);
3938
+ const pnpm = await readFile7(join20(root, "pnpm-workspace.yaml"), "utf8").catch(() => null);
3757
3939
  if (pnpm !== null) {
3758
3940
  try {
3759
3941
  const globs2 = strings((0, import_yaml3.parse)(pnpm)?.packages);
@@ -3767,8 +3949,8 @@ async function workspaceGlobs(root, pkg) {
3767
3949
  }
3768
3950
  var hasUi = async (dir) => (await findFiles(dir, UI_FILES, DEFAULT_EXCLUDE)).length > 0;
3769
3951
  async function findProjects(dir) {
3770
- const root = resolve12(dir);
3771
- const pkg = await readJson(join19(root, "package.json"));
3952
+ const root = resolve13(dir);
3953
+ const pkg = await readJson(join20(root, "package.json"));
3772
3954
  const name = typeof pkg?.name === "string" && pkg.name.trim() ? pkg.name.trim() : basename4(root);
3773
3955
  const single = { dir: ".", root, name: typeof pkg?.name === "string" ? pkg.name : null };
3774
3956
  const workspace = await workspaceGlobs(root, pkg);
@@ -3779,12 +3961,12 @@ async function findProjects(dir) {
3779
3961
  const projects = [];
3780
3962
  const skipped = [];
3781
3963
  for (const member of members) {
3782
- const memberRoot = join19(root, member);
3964
+ const memberRoot = join20(root, member);
3783
3965
  if (!await hasUi(memberRoot)) {
3784
3966
  skipped.push(member);
3785
3967
  continue;
3786
3968
  }
3787
- const memberPkg = await readJson(join19(memberRoot, "package.json"));
3969
+ const memberPkg = await readJson(join20(memberRoot, "package.json"));
3788
3970
  projects.push({ dir: member, root: memberRoot, name: typeof memberPkg?.name === "string" ? memberPkg.name : null });
3789
3971
  }
3790
3972
  if (projects.length === 0) return { root, name, layout: `one project (${workspace.source} names no package with UI files)`, projects: [single], skipped };
@@ -3811,7 +3993,7 @@ var Lines = class {
3811
3993
  if (!this.enabled) return { at };
3812
3994
  let lines = this.files.get(file);
3813
3995
  if (!lines) {
3814
- lines = (await readFile8(join20(this.root, file), "utf8").catch(() => "")).split("\n");
3996
+ lines = (await readFile8(join21(this.root, file), "utf8").catch(() => "")).split("\n");
3815
3997
  this.files.set(file, lines);
3816
3998
  }
3817
3999
  const code = lines[line - 1]?.trim();
@@ -3826,15 +4008,15 @@ function hardcodedValue(finding3) {
3826
4008
  const value = bracket ?? (declaration ? `${declaration[2]} (${declaration[1]})` : finding3.text);
3827
4009
  return { word: word === "type" ? "text size" : word, value, tokens };
3828
4010
  }
3829
- async function modulesOf(project2, target, failed) {
4011
+ async function modulesOf(project2, target, failed2) {
3830
4012
  const modules = [];
3831
4013
  for (const file of target.files) {
3832
4014
  if (isShowcase(file)) continue;
3833
4015
  try {
3834
- const module = await parseModule(file, await readFile8(join20(project2.root, file), "utf8"));
4016
+ const module = await parseModule(file, await readFile8(join21(project2.root, file), "utf8"));
3835
4017
  if (module) modules.push(module);
3836
4018
  } catch (error) {
3837
- failed.push(`${repoPath(project2.dir, file)}: ${errorText(error)}`);
4019
+ failed2.push(`${repoPath(project2.dir, file)}: ${errorText(error)}`);
3838
4020
  }
3839
4021
  }
3840
4022
  return modules;
@@ -3855,7 +4037,7 @@ async function grouped(project2, found, lines, describe) {
3855
4037
  return findings2.sort((a, b) => b.count - a.count || a.title.localeCompare(b.title));
3856
4038
  }
3857
4039
  async function analyseProject(project2, index, inventory, inventoryError, workspaceNames, lines) {
3858
- const failed = [];
4040
+ const failed2 = [];
3859
4041
  const incomplete = [];
3860
4042
  const notes = [];
3861
4043
  const projectId = inventory?.projects[index]?.id;
@@ -3863,7 +4045,7 @@ async function analyseProject(project2, index, inventory, inventoryError, worksp
3863
4045
  let target = null;
3864
4046
  try {
3865
4047
  target = await loadInventoryTarget(project2.root);
3866
- modules = await modulesOf(project2, target, failed);
4048
+ modules = await modulesOf(project2, target, failed2);
3867
4049
  } catch (error) {
3868
4050
  incomplete.push(`The code could not be read (${errorText(error)})`);
3869
4051
  }
@@ -3906,7 +4088,7 @@ async function analyseProject(project2, index, inventory, inventoryError, worksp
3906
4088
  const components = [...byComponent.values()].map((c) => ({ name: c.name, file: c.file, uses: c.roles.length, role: [...new Set(c.roles)].sort((a, b) => c.roles.filter((r) => r === b).length - c.roles.filter((r) => r === a).length)[0] })).sort((a, b) => b.uses - a.uses || a.name.localeCompare(b.name)).slice(0, TOP_COMPONENTS);
3907
4089
  const inventoryProject = inventory?.projects[index];
3908
4090
  if (inventoryError) incomplete.push(`The component inventory could not be built (${inventoryError}); run ${NPX} inventory --project ${project2.dir} to see why`);
3909
- for (const f of inventoryProject?.failed ?? []) failed.push(`${repoPath(project2.dir, f.file)}: ${f.reason}`);
4091
+ for (const f of inventoryProject?.failed ?? []) failed2.push(`${repoPath(project2.dir, f.file)}: ${f.reason}`);
3910
4092
  let hardcoded = [];
3911
4093
  let offLibrary = [];
3912
4094
  const everyLine = () => true;
@@ -3935,7 +4117,7 @@ async function analyseProject(project2, index, inventory, inventoryError, worksp
3935
4117
  incomplete.push(`Library choices were not compared (${errorText(error)}); run ${NPX} detect ${project2.dir} to see why`);
3936
4118
  }
3937
4119
  }
3938
- const pkg = await readFile8(join20(project2.root, "package.json"), "utf8").then((text) => JSON.parse(text), () => null);
4120
+ const pkg = await readFile8(join21(project2.root, "package.json"), "utf8").then((text) => JSON.parse(text), () => null);
3939
4121
  const dependencies = new Set(["dependencies", "devDependencies", "peerDependencies"].flatMap((key2) => Object.keys(pkg?.[key2] ?? {})));
3940
4122
  const importer = changeProject ? await importOf(changeProject) : () => "";
3941
4123
  const facts = factsOf(project2, projectId ?? null, modules, eligible, workspaceNames, dependencies, target?.files ?? [], importer);
@@ -3943,7 +4125,7 @@ async function analyseProject(project2, index, inventory, inventoryError, worksp
3943
4125
  dir: project2.dir,
3944
4126
  name: project2.name,
3945
4127
  files: inventoryProject?.files ?? modules.length,
3946
- failed,
4128
+ failed: failed2,
3947
4129
  libraries,
3948
4130
  unused,
3949
4131
  definitions: inventory ? inventory.definitions.filter((d) => d.project === projectId && !isShowcase(d.file)).length : 0,
@@ -4379,36 +4561,36 @@ ${model.projects.map((p) => projectSection(p, many, looks)).join("\n")}
4379
4561
  import { spawn as spawn2 } from "node:child_process";
4380
4562
  import { existsSync as existsSync4, readFileSync as readFileSync2 } from "node:fs";
4381
4563
  import { homedir as homedir2 } from "node:os";
4382
- import { dirname as dirname11, join as join21 } from "node:path";
4564
+ import { dirname as dirname12, join as join22 } from "node:path";
4383
4565
  var LOOKS_PER_PROJECT = 4;
4384
4566
  var DOWNLOAD_SIZE = "~100 MB";
4385
4567
  var DEPENDENCIES = "Install the repo's dependencies to see rendered looks";
4386
4568
  var UNDRAWABLE = /not installed|loads no stylesheet|drawn from (?:its|their) (?:tag and )?classes|did not render|bundle failed|unstyled|stub fallback/i;
4387
- var playwrightDir = () => dirname11(playwrightCli());
4569
+ var playwrightDir = () => dirname12(playwrightCli());
4388
4570
  function browsersPath(env) {
4389
4571
  const set = env.PLAYWRIGHT_BROWSERS_PATH;
4390
- if (set === "0") return join21(playwrightDir(), ".local-browsers");
4572
+ if (set === "0") return join22(playwrightDir(), ".local-browsers");
4391
4573
  if (set) return set;
4392
- if (process.platform === "darwin") return join21(homedir2(), "Library/Caches/ms-playwright");
4393
- if (process.platform === "win32") return join21(env.LOCALAPPDATA ?? join21(homedir2(), "AppData/Local"), "ms-playwright");
4394
- return join21(env.XDG_CACHE_HOME ?? join21(homedir2(), ".cache"), "ms-playwright");
4574
+ if (process.platform === "darwin") return join22(homedir2(), "Library/Caches/ms-playwright");
4575
+ if (process.platform === "win32") return join22(env.LOCALAPPDATA ?? join22(homedir2(), "AppData/Local"), "ms-playwright");
4576
+ return join22(env.XDG_CACHE_HOME ?? join22(homedir2(), ".cache"), "ms-playwright");
4395
4577
  }
4396
4578
  function chromiumStatus(env = process.env) {
4397
4579
  if (env.YOUI_CHROMIUM) return { available: existsSync4(env.YOUI_CHROMIUM), where: env.YOUI_CHROMIUM };
4398
4580
  try {
4399
- const browsers = JSON.parse(readFileSync2(join21(playwrightDir(), "browsers.json"), "utf8"));
4581
+ const browsers = JSON.parse(readFileSync2(join22(playwrightDir(), "browsers.json"), "utf8"));
4400
4582
  const revision2 = browsers.browsers.find((b) => b.name === "chromium-headless-shell")?.revision;
4401
- const dir = join21(browsersPath(env), `chromium_headless_shell-${revision2}`);
4402
- return { available: revision2 !== void 0 && existsSync4(join21(dir, "INSTALLATION_COMPLETE")), where: dir };
4583
+ const dir = join22(browsersPath(env), `chromium_headless_shell-${revision2}`);
4584
+ return { available: revision2 !== void 0 && existsSync4(join22(dir, "INSTALLATION_COMPLETE")), where: dir };
4403
4585
  } catch {
4404
4586
  return { available: false, where: "playwright-core is not installed" };
4405
4587
  }
4406
4588
  }
4407
4589
  function downloadChromium() {
4408
- return new Promise((resolve15) => {
4409
- const child = spawn2(process.execPath, [join21(playwrightDir(), "cli.js"), "install", "chromium-headless-shell"], { stdio: ["ignore", 2, 2] });
4410
- child.on("error", () => resolve15(false));
4411
- child.on("close", (code) => resolve15(code === 0));
4590
+ return new Promise((resolve16) => {
4591
+ const child = spawn2(process.execPath, [join22(playwrightDir(), "cli.js"), "install", "chromium-headless-shell"], { stdio: ["ignore", 2, 2] });
4592
+ child.on("error", () => resolve16(false));
4593
+ child.on("close", (code) => resolve16(code === 0));
4412
4594
  });
4413
4595
  }
4414
4596
  var dataUri = (file) => file && existsSync4(file) ? `data:image/png;base64,${readFileSync2(file).toString("base64")}` : null;
@@ -4422,24 +4604,24 @@ async function addLooks(model, repoRoot, options = {}) {
4422
4604
  const where2 = section.dir === "." ? "this repo" : section.dir;
4423
4605
  try {
4424
4606
  const installed = (name) => {
4425
- let dir = join21(repoRoot, section.dir);
4607
+ let dir = join22(repoRoot, section.dir);
4426
4608
  while (true) {
4427
- if (existsSync4(join21(dir, "node_modules", name, "package.json"))) return true;
4428
- if (dir === repoRoot || dirname11(dir) === dir) return false;
4429
- dir = dirname11(dir);
4609
+ if (existsSync4(join22(dir, "node_modules", name, "package.json"))) return true;
4610
+ if (dir === repoRoot || dirname12(dir) === dir) return false;
4611
+ dir = dirname12(dir);
4430
4612
  }
4431
4613
  };
4432
4614
  if (!installed("react") || !installed("react-dom")) {
4433
4615
  missing.push(where2);
4434
4616
  continue;
4435
4617
  }
4436
- const projectRoot = join21(repoRoot, section.dir);
4618
+ const projectRoot = join22(repoRoot, section.dir);
4437
4619
  const target = await loadInventoryTarget(projectRoot);
4438
4620
  if (findStylesheets(projectRoot, target.files, { tsconfig: target.tsconfig, override: target.specimenCss, templates: target.templates }).found.length === 0) {
4439
4621
  missing.push(where2);
4440
4622
  continue;
4441
4623
  }
4442
- const report = await renderShots(join21(repoRoot, section.dir), names, { download: false, base: "HEAD", ...options.executablePath ? { executablePath: options.executablePath } : {}, ...options.cache ? { cache: options.cache } : {}, ...options.log ? { log: options.log } : {} });
4624
+ 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 } : {} });
4443
4625
  const unavailable = report.notes.some((note) => UNDRAWABLE.test(note));
4444
4626
  if (unavailable) {
4445
4627
  missing.push(where2);
@@ -4511,7 +4693,7 @@ function renderMarkdown(model, reportFile) {
4511
4693
  import { realpathSync as realpathSync2 } from "node:fs";
4512
4694
  import { readFile as readFile9 } from "node:fs/promises";
4513
4695
  import { homedir as homedir3, userInfo as userInfo2 } from "node:os";
4514
- import { join as join22 } from "node:path";
4696
+ import { join as join23 } from "node:path";
4515
4697
  var REDACTED = "[redacted]";
4516
4698
  var OUTSIDE = "[path outside the repo]";
4517
4699
  var MIN_VALUE = 6;
@@ -4523,7 +4705,7 @@ async function dotenvValues(root) {
4523
4705
  const files = await findFiles(root, [".env", ".env.*", "**/.env", "**/.env.*"]).catch(() => []);
4524
4706
  const values = [];
4525
4707
  for (const file of files) {
4526
- const text = await readFile9(join22(root, file), "utf8").catch(() => "");
4708
+ const text = await readFile9(join23(root, file), "utf8").catch(() => "");
4527
4709
  for (const line of text.split(/\r?\n/)) {
4528
4710
  const match = /^\s*(?:export\s+)?[A-Za-z_][A-Za-z0-9_.-]*\s*=\s*(.*)$/.exec(line);
4529
4711
  if (!match) continue;
@@ -4650,12 +4832,12 @@ async function askTerminal(question) {
4650
4832
  }
4651
4833
  }
4652
4834
  async function writeBinaryAtomic(file, bytes) {
4653
- const temp = `${file}.${process.pid}.${randomBytes2(6).toString("hex")}.tmp`;
4835
+ const temp = `${file}.${process.pid}.${randomBytes3(6).toString("hex")}.tmp`;
4654
4836
  await writeFile2(temp, bytes);
4655
4837
  await rename3(temp, file);
4656
4838
  }
4657
4839
  var shown = (file) => {
4658
- const rel = relative9(process.cwd(), file);
4840
+ const rel = relative10(process.cwd(), file);
4659
4841
  return rel && !rel.startsWith("..") ? rel : file;
4660
4842
  };
4661
4843
  async function runReport(options = {}, io = {}) {
@@ -4664,7 +4846,7 @@ async function runReport(options = {}, io = {}) {
4664
4846
  const error = io.error ?? ((text) => void process.stderr.write(`${text}
4665
4847
  `));
4666
4848
  const env = io.env ?? process.env;
4667
- const root = resolve13(options.path ?? process.cwd());
4849
+ const root = resolve14(options.path ?? process.cwd());
4668
4850
  if (!(await stat3(root).catch(() => null))?.isDirectory()) {
4669
4851
  error(`\u2716 ${options.path ?? root} is not a directory: run ${NPX} in a repo, or pass its path (${NPX} path/to/repo)`);
4670
4852
  return { code: 2, files: null, model: null };
@@ -4694,9 +4876,9 @@ async function runReport(options = {}, io = {}) {
4694
4876
  model.durationMs += Math.round(performance.now() - started);
4695
4877
  const redactor = await Redactor.forRepo(root, { includeCode: options.includeCode === true, env });
4696
4878
  const clean = redactor.model(model);
4697
- const outDir = resolve13(options.out ?? root);
4879
+ const outDir = resolve14(options.out ?? root);
4698
4880
  await mkdir5(outDir, { recursive: true });
4699
- const files = { report: join23(outDir, REPORT_FILE), card: join23(outDir, CARD_FILE), summary: join23(outDir, SUMMARY_FILE) };
4881
+ const files = { report: join24(outDir, REPORT_FILE), card: join24(outDir, CARD_FILE), summary: join24(outDir, SUMMARY_FILE) };
4700
4882
  const t = clean.totals;
4701
4883
  const card = {
4702
4884
  repo: redactor.scrub(clean.repo),
@@ -4780,6 +4962,11 @@ ${style.bold("Anywhere")} ${style.dim("no design system needed")}
4780
4962
  an unchanged component comes from the cache (YOUI_SPECIMEN_CACHE)
4781
4963
 
4782
4964
  ${style.bold("In a product repo")}
4965
+ status [--json] where the product stands with its design system, in a few lines: the System
4966
+ and its source, what a sync would change (a dry run, offline), local drift,
4967
+ errors and warnings (beyond the baseline), components used, open requests,
4968
+ and the one thing to do next. In a workspace (youi.workspace.json, or a repo
4969
+ holding several products), one block per product
4783
4970
  adopt [--components dir] [--css file] [--system id] [--fork] [--dry-run]
4784
4971
  make this product's own UI its design system, kept in this repo: a draft
4785
4972
  contract per component in the components folder (the files stay where they
@@ -4883,7 +5070,8 @@ ${style.bold("Detect")} ${style.dim("which UI libraries a repo or website uses
4883
5070
 
4884
5071
  ${style.bold("The hub")}
4885
5072
  ui [--design dir] [--project dir] [--config file] [--root dir] [--port n] [--watch] [--state dir] [--inventory file] [--detect file]
4886
- open the web hub on a design system (default: the demo system);
5073
+ open the web hub on a design system (default: the demo system; beside a
5074
+ youi.workspace.json, its products, with Work > Workspace to switch);
4887
5075
  --project adds that product's usage map (read-only scan) and the
4888
5076
  rule editor (System > Rules, Work > Changes): drafts, impact preview,
4889
5077
  approval, a review branch in the design repo (drafts kept in --state);
@@ -4992,10 +5180,10 @@ async function readJsonOrFile(value) {
4992
5180
  async function cmdScan(values) {
4993
5181
  const p = await project(values);
4994
5182
  const { report } = await scanProject(p);
4995
- const out = values.out ?? join24(p.root, ".youi/usage.json");
4996
- await writeFileAtomic(resolve14(out), `${JSON.stringify(report)}
5183
+ const out = values.out ?? join25(p.root, ".youi/usage.json");
5184
+ await writeFileAtomic(resolve15(out), `${JSON.stringify(report)}
4997
5185
  `);
4998
- const recorded = await recordUsage(values, p, report, resolve14(out));
5186
+ const recorded = await recordUsage(values, p, report, resolve15(out));
4999
5187
  if (values.json) json3(report);
5000
5188
  else print([renderScan(report, out), ...recorded ? [recorded] : []].join("\n"));
5001
5189
  return 0;
@@ -5004,7 +5192,7 @@ async function recordUsage(values, p, report, usage) {
5004
5192
  const { path, home } = indexOf(values);
5005
5193
  try {
5006
5194
  await recordProject(await sharedStore(path), p, report);
5007
- await noteSource(home, { project: { root: resolve14(values.project ?? process.cwd()), options: Object.fromEntries(Object.entries(loadOptions(values)).map(([key2, value]) => [key2, resolve14(value)])), usage } });
5195
+ await noteSource(home, { project: { root: resolve15(values.project ?? process.cwd()), options: Object.fromEntries(Object.entries(loadOptions(values)).map(([key2, value]) => [key2, resolve15(value)])), usage } });
5008
5196
  return null;
5009
5197
  } catch (error) {
5010
5198
  return notRecorded(error);
@@ -5019,17 +5207,17 @@ function indexOf(values) {
5019
5207
  }
5020
5208
  async function cmdGaps(values) {
5021
5209
  const dirs = inventoryDirs(values);
5022
- const inventory = values.inventory ? InventoryReport.parse(JSON.parse(await readFile10(resolve14(values.inventory), "utf8"))) : await scanInventory(values, dirs);
5023
- const cwd = values.inventory ? dirname12(resolve14(values.inventory)) : process.cwd();
5024
- const project2 = await loadProject(resolve14(dirs[0]), loadOptions(values)).catch(() => null);
5210
+ const inventory = values.inventory ? InventoryReport.parse(JSON.parse(await readFile10(resolve15(values.inventory), "utf8"))) : await scanInventory(values, dirs);
5211
+ const cwd = values.inventory ? dirname13(resolve15(values.inventory)) : process.cwd();
5212
+ const project2 = await loadProject(resolve15(dirs[0]), loadOptions(values)).catch(() => null);
5025
5213
  const system = project2 ? { name: project2.system.config.name, components: project2.system.components.map((c) => c.contract.name) } : null;
5026
- const store = await readCatalog(resolve14(discoverCacheDir(values.cache)), indexOf(values).path).catch((error) => {
5214
+ const store = await readCatalog(resolve15(discoverCacheDir(values.cache)), indexOf(values).path).catch((error) => {
5027
5215
  if (error instanceof MissingIndexError) return null;
5028
5216
  throw error;
5029
5217
  });
5030
- const roots = new Map(inventory.projects.map((p) => [p.id, resolve14(cwd, p.root)]));
5218
+ const roots = new Map(inventory.projects.map((p) => [p.id, resolve15(cwd, p.root)]));
5031
5219
  const report = await buildGaps({ inventory, system, dependencies: declaredPackages(roots) }, store);
5032
- if (values.out) await writeFileAtomic(resolve14(values.out), `${JSON.stringify(report, null, 2)}
5220
+ if (values.out) await writeFileAtomic(resolve15(values.out), `${JSON.stringify(report, null, 2)}
5033
5221
  `);
5034
5222
  if (values.json) json3(report);
5035
5223
  else print(renderGaps(report));
@@ -5039,12 +5227,12 @@ async function cmdInventory(values) {
5039
5227
  if (values.history) return cmdHistory(values, []);
5040
5228
  const dirs = inventoryDirs(values);
5041
5229
  const report = await scanInventory(values, dirs);
5042
- const out = resolve14(values.out ?? join24(dirs[0], ".youi/inventory.json"));
5230
+ const out = resolve15(values.out ?? join25(dirs[0], ".youi/inventory.json"));
5043
5231
  await writeFileAtomic(out, `${JSON.stringify(report, null, 2)}
5044
5232
  `);
5045
5233
  const recorded = await recordScan(values, report, out);
5046
5234
  if (values.json) json3(report);
5047
- else print([renderInventory(report, relative10(process.cwd(), out).startsWith("..") ? out : relative10(process.cwd(), out)), recorded].join("\n"));
5235
+ else print([renderInventory(report, relative11(process.cwd(), out).startsWith("..") ? out : relative11(process.cwd(), out)), recorded].join("\n"));
5048
5236
  return 0;
5049
5237
  }
5050
5238
  async function recordScan(values, report, out) {
@@ -5069,7 +5257,7 @@ async function cmdIndex(values, positionals) {
5069
5257
  const [action, ...rest] = positionals;
5070
5258
  const { path, home } = indexOf(values);
5071
5259
  if (action === "path") {
5072
- if (values.json) json3({ store: storeLocation({ path }), sources: join24(home, SOURCES_FILE), scans: join24(home, SCANS_LOG) });
5260
+ if (values.json) json3({ store: storeLocation({ path }), sources: join25(home, SOURCES_FILE), scans: join25(home, SCANS_LOG) });
5073
5261
  else print(storeLocation({ path }));
5074
5262
  return 0;
5075
5263
  }
@@ -5080,7 +5268,7 @@ async function cmdIndex(values, positionals) {
5080
5268
  return 0;
5081
5269
  }
5082
5270
  if (action === "rebuild") {
5083
- const summary = await rebuildIndex(path, values.cache ? { discoverCache: resolve14(values.cache) } : {});
5271
+ const summary = await rebuildIndex(path, values.cache ? { discoverCache: resolve15(values.cache) } : {});
5084
5272
  if (values.json) json3(summary);
5085
5273
  else print(renderRebuild(summary));
5086
5274
  return 0;
@@ -5120,7 +5308,7 @@ async function cmdBom(values, positionals) {
5120
5308
  return 0;
5121
5309
  }
5122
5310
  function baselineFile(values, p) {
5123
- if (values["baseline-file"]) return resolve14(values["baseline-file"]);
5311
+ if (values["baseline-file"]) return resolve15(values["baseline-file"]);
5124
5312
  return values.baseline ? baselinePath(p, values.config) : null;
5125
5313
  }
5126
5314
  var checkScope = (values, positionals) => ({ ...positionals.length > 0 ? { files: positionals } : {}, ...values.rule ? { rule: values.rule } : {}, quiet: values.quiet });
@@ -5177,7 +5365,7 @@ async function cmdBaseline(values) {
5177
5365
  const { totals } = written.baseline;
5178
5366
  if (values.json) json3({ file: written.file, action: written.action, totals, notAdded: written.notAdded, identity: written.baseline.identity });
5179
5367
  else {
5180
- print(`${style.ok(written.action)} ${relative10(process.cwd(), file) || file}: ${plural(totals.errors, "error")} \xB7 ${plural(totals.warnings, "warning")} accepted`);
5368
+ print(`${style.ok(written.action)} ${relative11(process.cwd(), file) || file}: ${plural(totals.errors, "error")} \xB7 ${plural(totals.warnings, "warning")} accepted`);
5181
5369
  print(style.dim(` rules ${describeIdentity(written.baseline.identity)}`));
5182
5370
  if (written.notAdded > 0) print(style.warn(` ${plural(written.notAdded, "current violation")} not added: fix them, or accept them deliberately with --force`));
5183
5371
  }
@@ -5248,7 +5436,7 @@ async function cmdInit(values) {
5248
5436
  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)");
5249
5437
  const root = values.project ?? process.cwd();
5250
5438
  const design = await designArg(values.design, root);
5251
- const result = await initProject({ root, ...design, schemaDir: join24(TOOL_ROOT, "schema"), ...values.system ? { system: values.system } : {}, ...values.components ? { componentsDir: values.components } : {}, force: values.force });
5439
+ const result = await initProject({ root, ...design, schemaDir: join25(TOOL_ROOT, "schema"), ...values.system ? { system: values.system } : {}, ...values.components ? { componentsDir: values.components } : {}, force: values.force });
5252
5440
  if (!values.json) {
5253
5441
  print(`${style.ok("created")} ${result.file}`);
5254
5442
  for (const note of result.notes) print(style.dim(` \xB7 ${note}`));
@@ -5258,28 +5446,28 @@ async function cmdInit(values) {
5258
5446
  return cmdSync({ ...design.package ? rest : values, project: root });
5259
5447
  }
5260
5448
  async function cmdAdopt(values) {
5261
- const root = resolve14(values.project ?? process.cwd());
5262
- if (await exists(join24(root, PROJECT_FILE))) throw new Error(`${root} already has ${PROJECT_FILE}: it follows a design system already (youiyoux sync updates it)`);
5449
+ const root = resolve15(values.project ?? process.cwd());
5450
+ 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)`);
5263
5451
  const plan = await planAdoption({ root, ...values.components ? { componentsDir: values.components } : {}, ...values.css ? { css: values.css } : {}, ...values.system ? { system: values.system } : {}, fork: values.fork });
5264
- const taken = (await Promise.all(plan.files.map(async (f) => await exists(join24(root, f.path)) ? f.path : null))).filter((f) => f !== null);
5452
+ const taken = (await Promise.all(plan.files.map(async (f) => await exists(join25(root, f.path)) ? f.path : null))).filter((f) => f !== null);
5265
5453
  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" : ""}`);
5266
5454
  if (values["dry-run"]) {
5267
5455
  if (values.json) json3(plan);
5268
5456
  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"));
5269
5457
  return 0;
5270
5458
  }
5271
- const stylesheet = plan.stylesheet ? await readFile10(join24(root, plan.stylesheet.path), "utf8") : null;
5459
+ const stylesheet = plan.stylesheet ? await readFile10(join25(root, plan.stylesheet.path), "utf8") : null;
5272
5460
  try {
5273
- for (const file of plan.files) await writeFileAtomic(join24(root, file.path), file.content);
5274
- if (plan.stylesheet) await writeFileAtomic(join24(root, plan.stylesheet.path), plan.stylesheet.content);
5275
- await initProject({ root, design: root, schemaDir: join24(TOOL_ROOT, "schema"), system: plan.system.id, componentsDir: plan.componentsDir, outputs: { ...plan.outputs, targets: [...plan.outputs.targets], dark: [...plan.outputs.dark] }, tokenSources: plan.tokenSources });
5461
+ for (const file of plan.files) await writeFileAtomic(join25(root, file.path), file.content);
5462
+ if (plan.stylesheet) await writeFileAtomic(join25(root, plan.stylesheet.path), plan.stylesheet.content);
5463
+ 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 });
5276
5464
  await syncProject(await loadProject(root), { dryRun: true });
5277
5465
  } catch (error) {
5278
- for (const file of [...plan.files.map((f) => f.path), PROJECT_FILE]) await rm6(join24(root, file), { force: true });
5279
- for (const folder of [...new Set(plan.files.map((f) => dirname12(f.path)))].sort((a, b) => b.length - a.length)) await rmdir3(join24(root, folder)).catch(() => void 0);
5280
- await rmdir3(join24(root, "design/components")).catch(() => void 0);
5281
- await rmdir3(join24(root, "design")).catch(() => void 0);
5282
- if (plan.stylesheet && stylesheet !== null) await writeFileAtomic(join24(root, plan.stylesheet.path), stylesheet);
5466
+ for (const file of [...plan.files.map((f) => f.path), PROJECT_FILE]) await rm6(join25(root, file), { force: true });
5467
+ 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);
5468
+ await rmdir3(join25(root, "design/components")).catch(() => void 0);
5469
+ await rmdir3(join25(root, "design")).catch(() => void 0);
5470
+ if (plan.stylesheet && stylesheet !== null) await writeFileAtomic(join25(root, plan.stylesheet.path), stylesheet);
5283
5471
  throw new Error(`adopt was undone, nothing kept: ${error instanceof Error ? error.message : String(error)}`);
5284
5472
  }
5285
5473
  if (!values.json) print([...adoptLines(plan), ""].join("\n"));
@@ -5305,6 +5493,12 @@ function adoptLines(plan, dryRun = false) {
5305
5493
  })
5306
5494
  ];
5307
5495
  }
5496
+ async function cmdStatus(values) {
5497
+ const report = await workspaceStatus(process.cwd(), values.project);
5498
+ if (values.json) json3(report);
5499
+ else print(renderStatus(report));
5500
+ return report.projects.length === 0 ? 1 : statusExitCode(report);
5501
+ }
5308
5502
  async function cmdSystem(values, positionals) {
5309
5503
  const [action, dir, ...extra] = positionals;
5310
5504
  if (action !== "extract" || dir === void 0 || extra.length > 0) throw new UsageError("youiyoux system extract <dir> [--package <name>] [--dry-run] (move the System youiyoux adopt keeps in this product into a design repo of its own)");
@@ -5324,7 +5518,7 @@ async function cmdSystem(values, positionals) {
5324
5518
  print([...lines, ""].join("\n"));
5325
5519
  const synced = await cmdSync({ ...values, project: p.root, package: void 0 });
5326
5520
  const git3 = `push it and set source to { "git": "<its url>", "ref": "v${result.system.version}" }`;
5327
- print(`Next: make ${relative10(process.cwd(), result.target) || "."} a repository of its own and commit it. For each app to follow it, ${values.package ? `publish ${values.package}, add it as a dependency and set source to { "package": "${values.package}" }, or ${git3}` : `${git3}, or publish it as an npm package (--package names it)`}. Change components there from now on: youiyoux sync merges them into each product`);
5521
+ print(`Next: make ${relative11(process.cwd(), result.target) || "."} a repository of its own and commit it. For each app to follow it, ${values.package ? `publish ${values.package}, add it as a dependency and set source to { "package": "${values.package}" }, or ${git3}` : `${git3}, or publish it as an npm package (--package names it)`}. Change components there from now on: youiyoux sync merges them into each product`);
5328
5522
  return synced;
5329
5523
  }
5330
5524
  async function cmdLink(values, positionals) {
@@ -5342,31 +5536,31 @@ async function cmdUnlink(values) {
5342
5536
  const root = values.project ?? process.cwd();
5343
5537
  const linked = await linkedDesign(root);
5344
5538
  if (linked !== null) await setLink(root, null);
5345
- print(linked ? `${style.ok("unlinked")} ${resolve14(root)} uses its config's source again` : `${resolve14(root)} was not linked`);
5539
+ print(linked ? `${style.ok("unlinked")} ${resolve15(root)} uses its config's source again` : `${resolve15(root)} was not linked`);
5346
5540
  return 0;
5347
5541
  }
5348
5542
  async function designArg(value, root) {
5349
- if (existsSync5(resolve14(value)) || !PACKAGE_NAME.test(value)) return { design: value };
5350
- return { design: await designRootOf({ package: value }, join24(resolve14(root), PROJECT_FILE), root), package: value };
5543
+ if (existsSync5(resolve15(value)) || !PACKAGE_NAME.test(value)) return { design: value };
5544
+ return { design: await designRootOf({ package: value }, join25(resolve15(root), PROJECT_FILE), root), package: value };
5351
5545
  }
5352
5546
  async function cmdBuild(values) {
5353
- const root = resolve14(values.design ?? process.cwd());
5547
+ const root = resolve15(values.design ?? process.cwd());
5354
5548
  const system = getSystem(await loadDesignRepo(root), values.system);
5355
5549
  if (safeId(system.config.id) === null) throw new Error(`Cannot build system ${JSON.stringify(system.config.id)}: the id must be a plain name without ".." or path separators.`);
5356
5550
  const output = OutputConfig.parse({ cssVarPrefix: values.prefix ?? "youi", targets: ["css-vars", "tailwind-v4", "ts", "react-native"] });
5357
5551
  const started = performance.now();
5358
5552
  const built = await buildTokens(root, system.config, output, { contracts: system.components.map((c) => c.contract) });
5359
- const out = resolve14(values.out ?? join24(root, "build", system.config.id));
5360
- const boundary = values.out ? out : join24(root, "build");
5361
- if (!within(boundary, out) || built.files.some((file) => !within(out, join24(out, file.path)))) throw new Error(`Cannot build system ${JSON.stringify(system.config.id)}: an output path leaves the output directory.`);
5362
- for (const file of built.files) await writeFileAtomic(join24(out, file.path), file.content);
5553
+ const out = resolve15(values.out ?? join25(root, "build", system.config.id));
5554
+ const boundary = values.out ? out : join25(root, "build");
5555
+ 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.`);
5556
+ for (const file of built.files) await writeFileAtomic(join25(out, file.path), file.content);
5363
5557
  if (values.json) json3({ out, files: built.files.map((f) => f.path), tokens: built.tokens.length });
5364
5558
  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)})`)}`);
5365
5559
  return 0;
5366
5560
  }
5367
5561
  async function cmdParity(values) {
5368
5562
  if (!values.css) throw new UsageError("youiyoux parity --css <file> [--prefix p]");
5369
- const root = resolve14(values.design ?? process.cwd());
5563
+ const root = resolve15(values.design ?? process.cwd());
5370
5564
  const system = getSystem(await loadDesignRepo(root), values.system);
5371
5565
  const prefix = values.prefix ?? "youi";
5372
5566
  const dark = { selector: values.dark ?? ':root[data-theme="dark"]' };
@@ -5384,16 +5578,16 @@ async function cmdParity(values) {
5384
5578
  async function cmdSchema(values) {
5385
5579
  const schemas = renderJsonSchemas();
5386
5580
  if (values.check) {
5387
- const dir = join24(values.design ? resolve14(values.design) : TOOL_ROOT, "schema");
5581
+ const dir = join25(values.design ? resolve15(values.design) : TOOL_ROOT, "schema");
5388
5582
  const stale = [];
5389
- for (const { file, content } of schemas) if (await readFile10(join24(dir, file), "utf8").catch(() => null) !== content) stale.push(file);
5583
+ for (const { file, content } of schemas) if (await readFile10(join25(dir, file), "utf8").catch(() => null) !== content) stale.push(file);
5390
5584
  if (values.json) json3({ dir, stale });
5391
5585
  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>" : ""}`);
5392
5586
  return stale.length === 0 ? 0 : 1;
5393
5587
  }
5394
5588
  if (values.write) {
5395
- const root = values.design ? resolve14(values.design) : TOOL_ROOT;
5396
- for (const { file, content } of schemas) await writeFileAtomic(join24(root, "schema", file), content);
5589
+ const root = values.design ? resolve15(values.design) : TOOL_ROOT;
5590
+ for (const { file, content } of schemas) await writeFileAtomic(join25(root, "schema", file), content);
5397
5591
  print(`${style.ok("wrote")} ${schemas.map((s) => s.file).join(", ")}`);
5398
5592
  } else json3(Object.fromEntries(schemas.map((s) => [s.file, JSON.parse(s.content)])));
5399
5593
  return 0;
@@ -5416,7 +5610,7 @@ async function cmdHooks(values, positionals) {
5416
5610
  if (action !== "install") throw new UsageError("youiyoux hooks install [--claude] [--git] [--ci [--diff]] [--strict] or youiyoux hooks run claude|pre-commit");
5417
5611
  const p = await loadCheckProject(values.project ?? process.cwd(), loadOptions(values), !values.project);
5418
5612
  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");
5419
- const target = { ...hookTarget(values), project: p.root, ...configured(p) && p.configFile && p.configFile !== join24(p.root, PROJECT_FILE) ? { config: p.configFile } : {}, ...values.root !== void 0 ? { root: p.root } : {} };
5613
+ 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 } : {} };
5420
5614
  const all = !values.claude && !values.git && !values.ci;
5421
5615
  const results = [];
5422
5616
  if (values.claude || all) results.push({ kind: "Claude Code", ...await installClaudeHook(await repoRootOf(p.root), hookCommand(TOOL_ROOT, "claude", target)) });
@@ -5431,11 +5625,11 @@ async function cmdHooks(values, positionals) {
5431
5625
  async function cmdAgents(values, positionals) {
5432
5626
  const [action] = positionals;
5433
5627
  if (action !== "install" && action !== "remove") throw new UsageError("youiyoux agents install|remove [--claude] [--codex] [--json]");
5434
- const projectRoot = resolve14(values.project ?? process.cwd());
5628
+ const projectRoot = resolve15(values.project ?? process.cwd());
5435
5629
  const repoRoot = await repoRootOf(projectRoot);
5436
- const target = { project: projectRoot, ...values.config ? { config: resolve14(values.config) } : {}, ...values.design ? { design: resolve14(values.design) } : {}, ...values.root !== void 0 ? { root: resolve14(values.root || ".") } : {} };
5630
+ const target = { project: projectRoot, ...values.config ? { config: resolve15(values.config) } : {}, ...values.design ? { design: resolve15(values.design) } : {}, ...values.root !== void 0 ? { root: resolve15(values.root || ".") } : {} };
5437
5631
  const server = mcpCommand(TOOL_ROOT, target);
5438
- const system = existsSync5(resolve14(values.config ?? join24(projectRoot, PROJECT_FILE))) ? await project(values) : null;
5632
+ const system = existsSync5(resolve15(values.config ?? join25(projectRoot, PROJECT_FILE))) ? await project(values) : null;
5439
5633
  const claudeServer = system && system.root === repoRoot ? { command: "node", args: mcpArgs(system) } : relativeTo(repoRoot, server);
5440
5634
  const both = !values.claude && !values.codex;
5441
5635
  const results = [];
@@ -5506,7 +5700,32 @@ async function startEditor(values, port) {
5506
5700
  return null;
5507
5701
  }
5508
5702
  }
5703
+ async function workspaceUi(values) {
5704
+ if (values.design || values.project || values.config || values.root) return null;
5705
+ const { roots, workspace } = await statusTargets(process.cwd());
5706
+ if (workspace === null || roots.length === 0) return null;
5707
+ print(style.dim(`reading the status of ${plural(roots.length, "product")}\u2026`));
5708
+ const report = await workspaceStatus(process.cwd());
5709
+ const first = report.projects.findIndex((p) => !("error" in p));
5710
+ if (first < 0) {
5711
+ print(renderStatus(report));
5712
+ throw new Error("no product in this workspace could be read: see each one's Next above");
5713
+ }
5714
+ const port = values.port ?? DEFAULT_HUB_PORT;
5715
+ let open = null;
5716
+ const hub = await startWorkspaceHub({ roots, current: first, status: () => workspaceStatus(process.cwd()), open: (root) => open ? open(root) : Promise.resolve(1) });
5717
+ print(`${style.ok("workspace hub")} http://localhost:${port}/workspace#key=${hub.key}`);
5718
+ print(style.dim(` ${plural(roots.length, "product")}; showing ${report.projects[first].root} first. Open the link: it carries this run's key, which switching needs`));
5719
+ print(style.dim(" Rules and Changes are read-only here; youiyoux ui --project <dir> opens the rule editor on one product"));
5720
+ try {
5721
+ return await runHub(TOOL_ROOT, { project: roots[first], port, api: hub.url, workspace: (snapshot) => open = snapshot, ...values.inventory ? { inventory: values.inventory } : {}, ...values.detect ? { detect: values.detect } : {} });
5722
+ } finally {
5723
+ await hub.close();
5724
+ }
5725
+ }
5509
5726
  async function cmdUi(values) {
5727
+ const workspace = await workspaceUi(values);
5728
+ if (workspace !== null) return workspace;
5510
5729
  const port = values.port ?? DEFAULT_HUB_PORT;
5511
5730
  const editor = await startEditor(values, port);
5512
5731
  try {
@@ -5518,20 +5737,20 @@ async function cmdUi(values) {
5518
5737
  async function cmdDetect(values, positionals) {
5519
5738
  const target = detectTarget(positionals);
5520
5739
  if (!target) throw new UsageError("youiyoux detect <repo-path> or youiyoux detect <url\u2026> [--expose] (one repo, or one or more URLs; not both)");
5521
- const { repoReport, siteReport, writeReport } = await import("./src-J6GPLCVO.js");
5522
- const out = resolve14(values.out ?? ".youi/detect");
5740
+ const { repoReport, siteReport, writeReport } = await import("./src-ZG7JU6YJ.js");
5741
+ const out = resolve15(values.out ?? ".youi/detect");
5523
5742
  const report = target.kind === "repo" ? await repoReport(target.path) : await siteReport(target.urls, { out, expose: values.expose, ...process.env.YOUI_CHROMIUM ? { executablePath: process.env.YOUI_CHROMIUM } : {} });
5524
5743
  const file = await writeReport(report, out);
5525
5744
  if (values.json) json3(report);
5526
5745
  else {
5527
- const shown2 = relative10(process.cwd(), file);
5746
+ const shown2 = relative11(process.cwd(), file);
5528
5747
  print(renderDetect(report, shown2 && !shown2.startsWith("..") ? shown2 : file));
5529
5748
  }
5530
5749
  return 0;
5531
5750
  }
5532
5751
  async function cmdRender(values, positionals, io) {
5533
- const root = resolve14(values.root ?? values.project ?? process.cwd());
5534
- const targets = positionals.map((t) => existsSync5(resolve14(t)) ? resolve14(t) : t);
5752
+ const root = resolve15(values.root ?? values.project ?? process.cwd());
5753
+ const targets = positionals.map((t) => existsSync5(resolve15(t)) ? resolve15(t) : t);
5535
5754
  try {
5536
5755
  const report = await renderShots(root, targets, { ...values.base ? { base: values.base } : {}, ...process.env.YOUI_CHROMIUM ? { executablePath: process.env.YOUI_CHROMIUM } : {}, ...io.render });
5537
5756
  if (values.json) json3({ ...report, next: shotsNext(report, (t) => `run youiyoux render${t ? ` ${t}` : ""} again`) });
@@ -5545,14 +5764,14 @@ async function cmdRender(values, positionals, io) {
5545
5764
  }
5546
5765
  }
5547
5766
  async function product(values) {
5548
- const project2 = await loadProject(resolve14(values.project ?? process.cwd()), loadOptions(values)).catch(() => null);
5549
- return { project: project2, root: project2?.root ?? resolve14(values.root ?? values.project ?? process.cwd()) };
5767
+ const project2 = await loadProject(resolve15(values.project ?? process.cwd()), loadOptions(values)).catch(() => null);
5768
+ return { project: project2, root: project2?.root ?? resolve15(values.root ?? values.project ?? process.cwd()) };
5550
5769
  }
5551
5770
  async function cmdRequests(values, positionals) {
5552
5771
  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>";
5553
5772
  const [action, id, ...rest] = positionals;
5554
5773
  if (rest.length > 0) throw new UsageError(usage);
5555
- const { RequestStore, requestBrief } = await import("./src-4JGIPP5A.js");
5774
+ const { RequestStore, requestBrief } = await import("./src-EUVBYTKY.js");
5556
5775
  const { project: project2, root } = await product(values);
5557
5776
  const store = new RequestStore(root, project2?.config.id ?? basename5(root));
5558
5777
  const agent = { kind: "agent", name: "youiyoux CLI" };
@@ -5584,17 +5803,17 @@ async function cmdScreens(values, positionals, io) {
5584
5803
  const usage = "youiyoux screens capture --base <url of the app in development> [--route <one route>] [--project dir] [--out <screens dir>] [--storage-state <signed-in session>] [--json] or youiyoux screens login --base <url> [--project dir] [--storage-state <file>]";
5585
5804
  if (!["capture", "login"].includes(positionals[0] ?? "") || positionals.length > 1 || !values.base) throw new UsageError(usage);
5586
5805
  const { root } = await product(values);
5587
- if (positionals[0] === "login") return screensLogin(values.base, values["storage-state"] ? resolve14(values["storage-state"]) : sessionFile(root), io);
5588
- const dir = resolve14(values.out ?? join24(root, ".youi/screens"));
5589
- if (!existsSync5(join24(dir, "screens.json"))) {
5806
+ if (positionals[0] === "login") return screensLogin(values.base, values["storage-state"] ? resolve15(values["storage-state"]) : sessionFile(root), io);
5807
+ const dir = resolve15(values.out ?? join25(root, ".youi/screens"));
5808
+ if (!existsSync5(join25(dir, "screens.json"))) {
5590
5809
  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":"/"}]}
5591
5810
  `);
5592
5811
  return 1;
5593
5812
  }
5594
- const session = chosenSession(root, values["storage-state"] ? resolve14(values["storage-state"]) : void 0);
5813
+ const session = chosenSession(root, values["storage-state"] ? resolve15(values["storage-state"]) : void 0);
5595
5814
  if (session?.saved) process.stderr.write(`${style.dim(`signed in with the session youiyoux screens login saved (${session.file}); delete it to capture signed out`)}
5596
5815
  `);
5597
- const { launchBrowser } = await import("./src-J6GPLCVO.js");
5816
+ const { launchBrowser } = await import("./src-ZG7JU6YJ.js");
5598
5817
  const browser = await launchBrowser(process.env.YOUI_CHROMIUM, { purpose: { what: "youiyoux screens capture", command: "youiyoux screens capture" } });
5599
5818
  try {
5600
5819
  const report = await captureScreens(dir, { base: values.base, root, browser, ...values.route ? { routes: [values.route] } : {}, ...session ? { storageState: session.file } : {}, log: (line) => process.stderr.write(`${style.dim(line)}
@@ -5651,7 +5870,7 @@ async function cmdReport(values, positionals, io) {
5651
5870
  return result.code;
5652
5871
  }
5653
5872
  async function cmdMcp(values) {
5654
- const { startStdioServer } = await import("./src-NWPGCDGH.js");
5873
+ const { startStdioServer } = await import("./src-YKPJ3PII.js");
5655
5874
  await startStdioServer({ projectRoot: values.project ?? process.cwd(), ...loadOptions(values), ...values.cache ? { discoverCache: values.cache } : {} });
5656
5875
  return -1;
5657
5876
  }
@@ -5662,7 +5881,7 @@ function positiveInt(value, flag) {
5662
5881
  return n;
5663
5882
  }
5664
5883
  async function cmdDiscover(values, positionals, io) {
5665
- const cacheDir = resolve14(discoverCacheDir(values.cache));
5884
+ const cacheDir = resolve15(discoverCacheDir(values.cache));
5666
5885
  const { path, home } = indexOf(values);
5667
5886
  const catalog = () => readCatalog(cacheDir, path);
5668
5887
  const [action, ...rest] = positionals;
@@ -5714,6 +5933,7 @@ ${style.dim(`store \u2192 ${storeLocation({ path })} (${plural(loaded.chosen, "l
5714
5933
  }
5715
5934
  var COMMANDS = {
5716
5935
  adopt: cmdAdopt,
5936
+ status: cmdStatus,
5717
5937
  system: cmdSystem,
5718
5938
  link: cmdLink,
5719
5939
  unlink: cmdUnlink,