teamix-evo 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2395,11 +2395,11 @@ var uninstallCommand = new Command5("uninstall").description(
2395
2395
  `Will remove ${removable.length} file(s); keep ${kept} managed file(s).`
2396
2396
  );
2397
2397
  if (!opts.yes) {
2398
- const confirm7 = await prompts.confirm({
2398
+ const confirm8 = await prompts.confirm({
2399
2399
  message: "\u786E\u8BA4\u5378\u8F7D tokens \u53D8\u4F53\uFF1F",
2400
2400
  initialValue: false
2401
2401
  });
2402
- if (prompts.isCancel(confirm7) || !confirm7) {
2402
+ if (prompts.isCancel(confirm8) || !confirm8) {
2403
2403
  logger.info("Cancelled.");
2404
2404
  return;
2405
2405
  }
@@ -4583,11 +4583,11 @@ async function runFullUninstall(args) {
4583
4583
  `Will remove ${resources.length} skill file(s) installed by ${SKILLS_PACKAGE3}.`
4584
4584
  );
4585
4585
  if (!opts.yes) {
4586
- const confirm7 = await prompts4.confirm({
4586
+ const confirm8 = await prompts4.confirm({
4587
4587
  message: "\u786E\u8BA4\u5378\u8F7D\uFF1F\u6B64\u64CD\u4F5C\u4F1A\u5220\u9664\u4E0A\u8FF0\u6587\u4EF6\u3002",
4588
4588
  initialValue: false
4589
4589
  });
4590
- if (prompts4.isCancel(confirm7) || !confirm7) {
4590
+ if (prompts4.isCancel(confirm8) || !confirm8) {
4591
4591
  logger.info("Cancelled.");
4592
4592
  return;
4593
4593
  }
@@ -4640,11 +4640,11 @@ async function runPartialUninstall(args) {
4640
4640
  `Will remove ${matched.length} skill(s): ${matched.join(", ")} (${toRemove.length} file(s)).`
4641
4641
  );
4642
4642
  if (!opts.yes) {
4643
- const confirm7 = await prompts4.confirm({
4643
+ const confirm8 = await prompts4.confirm({
4644
4644
  message: "\u786E\u8BA4\u5378\u8F7D\uFF1F\u6B64\u64CD\u4F5C\u4F1A\u5220\u9664\u4E0A\u8FF0\u6587\u4EF6\u3002",
4645
4645
  initialValue: false
4646
4646
  });
4647
- if (prompts4.isCancel(confirm7) || !confirm7) {
4647
+ if (prompts4.isCancel(confirm8) || !confirm8) {
4648
4648
  logger.info("Cancelled.");
4649
4649
  return;
4650
4650
  }
@@ -9687,155 +9687,18 @@ var migrateCommand = new Command38("migrate").description(
9687
9687
 
9688
9688
  // src/commands/graft/index.ts
9689
9689
  import { Command as Command39 } from "commander";
9690
- import * as path43 from "path";
9691
- import * as fs31 from "fs/promises";
9692
- init_logger();
9693
- init_error();
9694
- init_fs();
9695
- var APP_ENTRY_CANDIDATES = [
9696
- "src/app.tsx",
9697
- "src/app.ts",
9698
- "src/app.jsx",
9699
- "src/app.js",
9700
- "src/index.tsx",
9701
- "src/index.ts",
9702
- "src/index.jsx",
9703
- "src/index.js"
9704
- ];
9705
- var POSTCSS_CONFIG_CANDIDATES = [
9706
- "postcss.config.js",
9707
- "postcss.config.cjs",
9708
- "postcss.config.mjs",
9709
- "postcss.config.ts",
9710
- ".postcssrc",
9711
- ".postcssrc.json",
9712
- ".postcssrc.yml",
9713
- ".postcssrc.yaml",
9714
- ".postcssrc.js"
9715
- ];
9716
- var CONFLICT_PATHS = [
9717
- { path: ".teamix-evo", type: "directory" },
9718
- { path: "src/components/ui", type: "directory" },
9719
- { path: "src/components/business", type: "directory" },
9720
- { path: "tokens", type: "directory" }
9721
- ];
9722
- async function findFirst(cwd, candidates) {
9723
- for (const c of candidates) {
9724
- if (await fileExists(path43.join(cwd, c))) return c;
9725
- }
9726
- return null;
9727
- }
9728
- async function getLegacyLibVersion(cwd, legacyLib) {
9729
- const pkgRaw = await readFileOrNull(path43.join(cwd, "package.json"));
9730
- if (!pkgRaw) return "unknown";
9731
- try {
9732
- const pkg = JSON.parse(pkgRaw);
9733
- const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
9734
- const libKeyMap = {
9735
- fusion: ["@alifd/next", "@ali/teamix-material"],
9736
- antd: ["antd"],
9737
- element: ["element-ui", "element-plus"]
9738
- };
9739
- const keys = libKeyMap[legacyLib] ?? [];
9740
- for (const key of keys) {
9741
- if (allDeps[key]) return allDeps[key];
9742
- }
9743
- } catch {
9744
- }
9745
- return "unknown";
9746
- }
9747
- async function detectConflicts(cwd) {
9748
- const conflicts = [];
9749
- for (const entry of CONFLICT_PATHS) {
9750
- const full = path43.join(cwd, entry.path);
9751
- try {
9752
- const stat6 = await fs31.stat(full);
9753
- if (entry.type === "directory" && stat6.isDirectory() || entry.type === "file" && stat6.isFile()) {
9754
- conflicts.push(entry);
9755
- }
9756
- } catch {
9757
- }
9758
- }
9759
- return conflicts;
9760
- }
9761
- var graftCommand = new Command39("graft").description(
9762
- "\u53E0\u52A0 Teamix Evo AICoding \u80FD\u529B\u5230\u73B0\u6709\u9879\u76EE\uFF08\u53CC\u6808\u5171\u5B58\uFF0CADR 0047\uFF09"
9763
- ).option("--variant <name>", "\u6307\u5B9A tokens variant\uFF08\u5982 opentrek\uFF09").option("--cwd <dir>", "\u6307\u5B9A\u5DE5\u7A0B\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4\uFF1A\u5F53\u524D\u76EE\u5F55\uFF09").option("--json", "\u8F93\u51FA JSON \u683C\u5F0F\u7684\u5206\u6790\u62A5\u544A\uFF08\u4F9B AI skill \u6D88\u8D39\uFF09").action(async (opts) => {
9764
- const cwd = path43.resolve(opts.cwd ?? process.cwd());
9765
- try {
9766
- const state = await detectProjectState(cwd);
9767
- if (state.state !== "other") {
9768
- assertCommandPrecondition("graft", state.state);
9769
- return;
9770
- }
9771
- const legacyLib = state.legacyLib ?? "unknown";
9772
- const buildTool = state.buildTool ?? "unknown";
9773
- const legacyVersion = await getLegacyLibVersion(cwd, legacyLib);
9774
- const BUILD_TOOL_CONFIG_CANDIDATES = {
9775
- ice: ["build.json"],
9776
- vite: ["vite.config.ts", "vite.config.js", "vite.config.mts", "vite.config.mjs"],
9777
- webpack: ["webpack.config.js", "webpack.config.ts", "webpack.config.cjs"]
9778
- };
9779
- const buildToolConfig = await findFirst(
9780
- cwd,
9781
- BUILD_TOOL_CONFIG_CANDIDATES[buildTool] ?? []
9782
- );
9783
- const postcssPath = await findFirst(cwd, POSTCSS_CONFIG_CANDIDATES);
9784
- const appEntry = await findFirst(cwd, APP_ENTRY_CANDIDATES);
9785
- const conflicts = await detectConflicts(cwd);
9786
- const report = {
9787
- projectRoot: cwd,
9788
- legacyLib: { name: legacyLib, version: legacyVersion },
9789
- buildTool: { type: buildTool, configFile: buildToolConfig },
9790
- postcssConfig: { exists: postcssPath !== null, path: postcssPath },
9791
- appEntry,
9792
- conflicts
9793
- };
9794
- if (opts.json) {
9795
- console.log(JSON.stringify(report, null, 2));
9796
- } else {
9797
- logger.info("Teamix Evo Graft \u2014 \u53CC\u6808\u5171\u5B58\u524D\u7F6E\u68C0\u67E5");
9798
- logger.info("");
9799
- logger.info(` \u9879\u76EE\u76EE\u5F55\uFF1A${cwd}`);
9800
- logger.info(
9801
- ` \u65E7\u7EC4\u4EF6\u5E93\uFF1A${legacyLib} (${legacyVersion})`
9802
- );
9803
- logger.info(` \u6784\u5EFA\u5DE5\u5177\uFF1A${buildTool}`);
9804
- logger.info(
9805
- ` PostCSS \u914D\u7F6E\uFF1A${postcssPath ?? "\u672A\u68C0\u6D4B\u5230"}`
9806
- );
9807
- logger.info(` App \u5165\u53E3\uFF1A${appEntry ?? "\u672A\u68C0\u6D4B\u5230"}`);
9808
- if (conflicts.length > 0) {
9809
- logger.info("");
9810
- logger.warn(" \u5DF2\u5B58\u5728\u7684\u8DEF\u5F84\uFF08\u53EF\u80FD\u51B2\u7A81\uFF09\uFF1A");
9811
- for (const c of conflicts) {
9812
- logger.warn(` ${c.path} (${c.type})`);
9813
- }
9814
- }
9815
- logger.info("");
9816
- logger.info(
9817
- "\u524D\u7F6E\u68C0\u67E5\u901A\u8FC7\u3002\u8BF7\u5728 AI IDE \u4E2D\u89E6\u53D1 teamix-evo-manage skill \u4EE5\u5F15\u5BFC graft \u6D41\u7A0B\u3002"
9818
- );
9819
- logger.info(
9820
- "CLI \u4EC5\u505A\u524D\u7F6E\u68C0\u67E5\uFF0C\u5B9E\u9645 graft \u7531 AI skill \u9A71\u52A8\u3002"
9821
- );
9822
- }
9823
- } catch (err) {
9824
- logger.error(`graft \u524D\u7F6E\u68C0\u67E5\u5931\u8D25\uFF1A${getErrorMessage(err)}`);
9825
- logger.debug(err.stack ?? "");
9826
- process.exitCode = 1;
9827
- }
9828
- });
9829
-
9830
- // src/commands/restore/index.ts
9831
- import { Command as Command40 } from "commander";
9832
9690
  import * as path45 from "path";
9691
+ import * as fs32 from "fs/promises";
9833
9692
  import * as prompts7 from "@clack/prompts";
9834
9693
 
9694
+ // src/core/graft-init.ts
9695
+ import { hasManagedRegion as hasManagedRegion5, replaceManagedRegion as replaceManagedRegion4 } from "@teamix-evo/registry";
9696
+ init_state();
9697
+
9835
9698
  // src/core/snapshot.ts
9836
9699
  init_logger();
9837
- import * as fs32 from "fs/promises";
9838
- import * as path44 from "path";
9700
+ import * as fs31 from "fs/promises";
9701
+ import * as path43 from "path";
9839
9702
  var TEAMIX_DIR6 = ".teamix-evo";
9840
9703
  var SNAPSHOTS_DIR = ".snapshots";
9841
9704
  var META_FILE = "_meta.json";
@@ -9851,9 +9714,9 @@ function fsSafeToIso(safe) {
9851
9714
  );
9852
9715
  }
9853
9716
  async function createSnapshot(projectRoot, opts = {}) {
9854
- const teamixDir = path44.join(projectRoot, TEAMIX_DIR6);
9717
+ const teamixDir = path43.join(projectRoot, TEAMIX_DIR6);
9855
9718
  try {
9856
- const stat6 = await fs32.stat(teamixDir);
9719
+ const stat6 = await fs31.stat(teamixDir);
9857
9720
  if (!stat6.isDirectory()) return null;
9858
9721
  } catch (err) {
9859
9722
  if (err.code === "ENOENT") return null;
@@ -9861,37 +9724,37 @@ async function createSnapshot(projectRoot, opts = {}) {
9861
9724
  }
9862
9725
  const isoTs = (/* @__PURE__ */ new Date()).toISOString();
9863
9726
  const ts = isoToFsSafe3(isoTs);
9864
- const snapshotRoot = path44.join(teamixDir, SNAPSHOTS_DIR);
9865
- const target = path44.join(snapshotRoot, ts);
9866
- await fs32.mkdir(target, { recursive: true });
9867
- const entries = await fs32.readdir(teamixDir, { withFileTypes: true });
9727
+ const snapshotRoot = path43.join(teamixDir, SNAPSHOTS_DIR);
9728
+ const target = path43.join(snapshotRoot, ts);
9729
+ await fs31.mkdir(target, { recursive: true });
9730
+ const entries = await fs31.readdir(teamixDir, { withFileTypes: true });
9868
9731
  for (const entry of entries) {
9869
9732
  if (entry.name === SNAPSHOTS_DIR) continue;
9870
- const src = path44.join(teamixDir, entry.name);
9871
- const dst = path44.join(target, entry.name);
9872
- await fs32.cp(src, dst, { recursive: true });
9733
+ const src = path43.join(teamixDir, entry.name);
9734
+ const dst = path43.join(target, entry.name);
9735
+ await fs31.cp(src, dst, { recursive: true });
9873
9736
  }
9874
9737
  const meta = {
9875
9738
  ts: isoTs,
9876
9739
  reason: opts.reason ?? "manual"
9877
9740
  };
9878
- await fs32.writeFile(
9879
- path44.join(target, META_FILE),
9741
+ await fs31.writeFile(
9742
+ path43.join(target, META_FILE),
9880
9743
  JSON.stringify(meta, null, 2) + "\n",
9881
9744
  "utf-8"
9882
9745
  );
9883
9746
  logger.debug(
9884
- `Snapshot created \u2192 ${path44.relative(projectRoot, target)} (${meta.reason})`
9747
+ `Snapshot created \u2192 ${path43.relative(projectRoot, target)} (${meta.reason})`
9885
9748
  );
9886
9749
  const keep = opts.keep ?? DEFAULT_KEEP;
9887
9750
  await pruneSnapshots(projectRoot, keep, { protectedTs: opts.protectedTs });
9888
9751
  return { ts, path: target };
9889
9752
  }
9890
9753
  async function listSnapshots(projectRoot) {
9891
- const snapshotRoot = path44.join(projectRoot, TEAMIX_DIR6, SNAPSHOTS_DIR);
9754
+ const snapshotRoot = path43.join(projectRoot, TEAMIX_DIR6, SNAPSHOTS_DIR);
9892
9755
  let entries;
9893
9756
  try {
9894
- entries = await fs32.readdir(snapshotRoot, { withFileTypes: true });
9757
+ entries = await fs31.readdir(snapshotRoot, { withFileTypes: true });
9895
9758
  } catch (err) {
9896
9759
  if (err.code === "ENOENT") return [];
9897
9760
  throw err;
@@ -9899,11 +9762,11 @@ async function listSnapshots(projectRoot) {
9899
9762
  const result = [];
9900
9763
  for (const entry of entries) {
9901
9764
  if (!entry.isDirectory()) continue;
9902
- const dir = path44.join(snapshotRoot, entry.name);
9765
+ const dir = path43.join(snapshotRoot, entry.name);
9903
9766
  let isoTs = null;
9904
9767
  let reason = null;
9905
9768
  try {
9906
- const raw = await fs32.readFile(path44.join(dir, META_FILE), "utf-8");
9769
+ const raw = await fs31.readFile(path43.join(dir, META_FILE), "utf-8");
9907
9770
  const parsed = JSON.parse(raw);
9908
9771
  if (typeof parsed.ts === "string") isoTs = parsed.ts;
9909
9772
  if (typeof parsed.reason === "string" && SNAPSHOT_REASONS.includes(
@@ -9928,17 +9791,17 @@ async function pruneSnapshots(projectRoot, keep = DEFAULT_KEEP, opts = {}) {
9928
9791
  const toRemove = opts.protectedTs ? tail.filter((s) => s.ts !== opts.protectedTs) : tail;
9929
9792
  const removed = [];
9930
9793
  for (const snap of toRemove) {
9931
- await fs32.rm(snap.path, { recursive: true, force: true });
9794
+ await fs31.rm(snap.path, { recursive: true, force: true });
9932
9795
  removed.push(snap.ts);
9933
9796
  logger.debug(`Pruned snapshot ${snap.ts}`);
9934
9797
  }
9935
9798
  return removed.reverse();
9936
9799
  }
9937
9800
  async function restoreSnapshot(projectRoot, ts) {
9938
- const snapshotRoot = path44.join(projectRoot, TEAMIX_DIR6, SNAPSHOTS_DIR);
9939
- const target = path44.join(snapshotRoot, ts);
9801
+ const snapshotRoot = path43.join(projectRoot, TEAMIX_DIR6, SNAPSHOTS_DIR);
9802
+ const target = path43.join(snapshotRoot, ts);
9940
9803
  try {
9941
- const stat6 = await fs32.stat(target);
9804
+ const stat6 = await fs31.stat(target);
9942
9805
  if (!stat6.isDirectory()) {
9943
9806
  throw new Error(`Snapshot path is not a directory: ${target}`);
9944
9807
  }
@@ -9951,33 +9814,566 @@ async function restoreSnapshot(projectRoot, ts) {
9951
9814
  throw err;
9952
9815
  }
9953
9816
  await createSnapshot(projectRoot, { reason: "restore", protectedTs: ts });
9954
- const teamixDir = path44.join(projectRoot, TEAMIX_DIR6);
9955
- const live = await fs32.readdir(teamixDir, { withFileTypes: true });
9817
+ const teamixDir = path43.join(projectRoot, TEAMIX_DIR6);
9818
+ const live = await fs31.readdir(teamixDir, { withFileTypes: true });
9956
9819
  for (const entry of live) {
9957
9820
  if (entry.name === SNAPSHOTS_DIR) continue;
9958
- await fs32.rm(path44.join(teamixDir, entry.name), {
9821
+ await fs31.rm(path43.join(teamixDir, entry.name), {
9959
9822
  recursive: true,
9960
9823
  force: true
9961
9824
  });
9962
9825
  }
9963
- const snapshotEntries = await fs32.readdir(target, { withFileTypes: true });
9826
+ const snapshotEntries = await fs31.readdir(target, { withFileTypes: true });
9964
9827
  for (const entry of snapshotEntries) {
9965
9828
  if (entry.name === META_FILE) continue;
9966
- const src = path44.join(target, entry.name);
9967
- const dst = path44.join(teamixDir, entry.name);
9968
- await fs32.cp(src, dst, { recursive: true });
9829
+ const src = path43.join(target, entry.name);
9830
+ const dst = path43.join(teamixDir, entry.name);
9831
+ await fs31.cp(src, dst, { recursive: true });
9969
9832
  }
9970
9833
  logger.debug(`Restored .teamix-evo/ from snapshot ${ts}`);
9971
9834
  }
9972
9835
 
9836
+ // src/core/graft-init.ts
9837
+ init_error();
9838
+ init_logger();
9839
+ init_fs();
9840
+ import * as fsNode2 from "fs/promises";
9841
+ import * as path44 from "path";
9842
+ var CRITICAL_STEPS2 = /* @__PURE__ */ new Set([
9843
+ "ensure-teamix-dir",
9844
+ "tokens",
9845
+ "ui-init",
9846
+ "skills"
9847
+ ]);
9848
+ var AGENTS_MD_GRAFT_MANAGED_ID = "teamix-evo-graft";
9849
+ var GITIGNORE_MARKER_START2 = "# >>> teamix-evo:managed >>>";
9850
+ var GITIGNORE_MARKER_END2 = "# <<< teamix-evo:managed <<<";
9851
+ var GITIGNORE_RULES2 = [
9852
+ "# Runtime artifacts (regenerable / archives)",
9853
+ ".teamix-evo/.snapshots/",
9854
+ ".teamix-evo/.backups/",
9855
+ ".teamix-evo/.upgrade-staging/",
9856
+ ".teamix-evo/.upgrade-hints/"
9857
+ ];
9858
+ var LEGACY_LIB_META = {
9859
+ fusion: {
9860
+ displayName: "Fusion Design",
9861
+ imports: ["teamix/ui", "@alifd/next", "@ali/teamix-material"]
9862
+ },
9863
+ antd: {
9864
+ displayName: "Ant Design",
9865
+ imports: ["antd", "@ant-design/*"]
9866
+ },
9867
+ element: {
9868
+ displayName: "Element UI",
9869
+ imports: ["element-ui", "element-plus"]
9870
+ }
9871
+ };
9872
+ async function runGraftInit(options) {
9873
+ const {
9874
+ projectRoot,
9875
+ variant,
9876
+ legacyLib,
9877
+ onStep
9878
+ } = options;
9879
+ const ide = options.ide ?? "qoder";
9880
+ const ides = options.ides ?? ["qoder", "claude"];
9881
+ const scope = options.scope ?? "project";
9882
+ const steps = [];
9883
+ let aborted = false;
9884
+ function record(step) {
9885
+ steps.push(step);
9886
+ onStep?.(step);
9887
+ }
9888
+ function recordFailure(name, err) {
9889
+ const message = getErrorMessage(err);
9890
+ record({ name, status: "fail", detail: message });
9891
+ if (CRITICAL_STEPS2.has(name)) aborted = true;
9892
+ }
9893
+ try {
9894
+ await ensureTeamixDir(projectRoot);
9895
+ record({ name: "ensure-teamix-dir", status: "ok" });
9896
+ } catch (err) {
9897
+ recordFailure("ensure-teamix-dir", err);
9898
+ }
9899
+ if (!aborted) {
9900
+ try {
9901
+ const snap = await createSnapshot(projectRoot, { reason: "graft" });
9902
+ record({
9903
+ name: "snapshot",
9904
+ status: "ok",
9905
+ detail: snap ? `snapshot ${snap.ts}` : "empty .teamix-evo/ \u2014 nothing to snapshot"
9906
+ });
9907
+ } catch (err) {
9908
+ recordFailure("snapshot", err);
9909
+ }
9910
+ } else {
9911
+ record({ name: "snapshot", status: "skip", detail: "aborted: earlier critical step failed" });
9912
+ }
9913
+ if (!aborted) {
9914
+ try {
9915
+ const result = await runTokensInit({ projectRoot, variant, ide });
9916
+ const detail = result.status === "installed" ? `${result.packageName}@${result.version} (${result.count} files)` : result.status;
9917
+ record({ name: "tokens", status: "ok", detail });
9918
+ } catch (err) {
9919
+ recordFailure("tokens", err);
9920
+ }
9921
+ } else {
9922
+ record({ name: "tokens", status: "skip", detail: "aborted: earlier critical step failed" });
9923
+ }
9924
+ if (!aborted) {
9925
+ try {
9926
+ const initResult = await runUiInit({ projectRoot, ide });
9927
+ record({
9928
+ name: "ui-init",
9929
+ status: "ok",
9930
+ detail: initResult.status === "installed" ? "config.json packages.ui written" : initResult.status
9931
+ });
9932
+ } catch (err) {
9933
+ recordFailure("ui-init", err);
9934
+ }
9935
+ } else {
9936
+ record({ name: "ui-init", status: "skip", detail: "aborted: earlier critical step failed" });
9937
+ }
9938
+ const collectedNpmDeps = {};
9939
+ if (!aborted) {
9940
+ try {
9941
+ const { manifest } = await loadUiData("@teamix-evo/ui");
9942
+ const allIds = manifest.entries.map((e) => e.id);
9943
+ const addResult = await runUiAdd({
9944
+ projectRoot,
9945
+ ids: allIds,
9946
+ overwrite: true
9947
+ });
9948
+ record({
9949
+ name: "ui-add",
9950
+ status: "ok",
9951
+ detail: `${addResult.orderedIds.length} entries (${addResult.written} written, ${addResult.skipped} skipped)`
9952
+ });
9953
+ Object.assign(collectedNpmDeps, addResult.npmDependencies);
9954
+ } catch (err) {
9955
+ recordFailure("ui-add", err);
9956
+ }
9957
+ } else {
9958
+ record({ name: "ui-add", status: "skip", detail: "aborted: earlier critical step failed" });
9959
+ }
9960
+ if (!aborted) {
9961
+ try {
9962
+ const listing = await listBizUiEntries(variant);
9963
+ if (listing.entries.length === 0) {
9964
+ record({
9965
+ name: "biz-ui-add",
9966
+ status: "skip",
9967
+ detail: `no biz-ui entries for variant "${variant}"`
9968
+ });
9969
+ } else {
9970
+ const allIds = listing.entries.map((e) => e.id);
9971
+ const result = await runBizUiAdd({
9972
+ projectRoot,
9973
+ variant,
9974
+ ids: allIds,
9975
+ overwrite: true
9976
+ });
9977
+ record({
9978
+ name: "biz-ui-add",
9979
+ status: "ok",
9980
+ detail: `${result.orderedIds.length} entries (${result.written} written, ${result.skipped} skipped)`
9981
+ });
9982
+ if (result.npmDependencies) {
9983
+ Object.assign(collectedNpmDeps, result.npmDependencies);
9984
+ }
9985
+ }
9986
+ } catch (err) {
9987
+ recordFailure("biz-ui-add", err);
9988
+ }
9989
+ } else {
9990
+ record({ name: "biz-ui-add", status: "skip", detail: "aborted: earlier critical step failed" });
9991
+ }
9992
+ if (!aborted && Object.keys(collectedNpmDeps).length > 0) {
9993
+ try {
9994
+ await installProjectDeps({
9995
+ projectRoot,
9996
+ npmDependencies: collectedNpmDeps,
9997
+ skipInstall: options.skipInstall ?? false
9998
+ });
9999
+ } catch (err) {
10000
+ logger.warn(
10001
+ `\u5B89\u88C5 ui/biz-ui \u4F20\u9012\u4F9D\u8D56\u5931\u8D25\uFF1A${getErrorMessage(err)}\uFF08\u53EF\u624B\u52A8\u8FD0\u884C \`npm install\` \u91CD\u8BD5\uFF09`
10002
+ );
10003
+ }
10004
+ }
10005
+ if (!aborted) {
10006
+ try {
10007
+ const result = await runSkillsInit({ projectRoot, ides, scope, ide });
10008
+ if (result.status === "already-initialized") {
10009
+ record({ name: "skills", status: "ok", detail: "already-initialized" });
10010
+ } else {
10011
+ record({
10012
+ name: "skills",
10013
+ status: "ok",
10014
+ detail: `${result.skillCount} skills, ${result.fileCount} files`
10015
+ });
10016
+ }
10017
+ } catch (err) {
10018
+ recordFailure("skills", err);
10019
+ }
10020
+ } else {
10021
+ record({ name: "skills", status: "skip", detail: "aborted: earlier critical step failed" });
10022
+ }
10023
+ if (!aborted) {
10024
+ try {
10025
+ const result = await runGenerateAgentsMd({
10026
+ projectRoot,
10027
+ variant,
10028
+ skillIds: [
10029
+ `teamix-evo-design-${variant}`,
10030
+ `teamix-evo-code-${variant}`
10031
+ ],
10032
+ globalSkillIds: ["teamix-evo-manage"],
10033
+ mode: "merge-managed"
10034
+ });
10035
+ record({
10036
+ name: "agents-md",
10037
+ status: "ok",
10038
+ detail: `${result.skillCount} skill index (${result.merge})`
10039
+ });
10040
+ } catch (err) {
10041
+ recordFailure("agents-md", err);
10042
+ }
10043
+ } else {
10044
+ record({ name: "agents-md", status: "skip", detail: "aborted" });
10045
+ }
10046
+ if (!aborted) {
10047
+ try {
10048
+ const agentsMdPath = path44.join(projectRoot, "AGENTS.md");
10049
+ const existing = await readFileOrNull(agentsMdPath) ?? "";
10050
+ const meta = LEGACY_LIB_META[legacyLib] ?? {
10051
+ displayName: legacyLib,
10052
+ imports: [legacyLib]
10053
+ };
10054
+ const importsStr = meta.imports.map((i) => `\`${i}\``).join("\u3001");
10055
+ const graftBody = renderGraftManagedBody(meta.displayName, importsStr);
10056
+ let output;
10057
+ if (hasManagedRegion5(existing, AGENTS_MD_GRAFT_MANAGED_ID)) {
10058
+ output = replaceManagedRegion4(
10059
+ existing,
10060
+ AGENTS_MD_GRAFT_MANAGED_ID,
10061
+ graftBody
10062
+ );
10063
+ } else {
10064
+ const wrapped = wrapGraftManagedBlock(graftBody);
10065
+ output = existing.trimEnd() + "\n\n" + wrapped + "\n";
10066
+ }
10067
+ await fsNode2.writeFile(agentsMdPath, output, "utf-8");
10068
+ record({ name: "agents-md-graft", status: "ok", detail: `dual-stack rules for ${legacyLib}` });
10069
+ } catch (err) {
10070
+ recordFailure("agents-md-graft", err);
10071
+ }
10072
+ } else {
10073
+ record({ name: "agents-md-graft", status: "skip", detail: "aborted" });
10074
+ }
10075
+ if (!aborted) {
10076
+ try {
10077
+ const uiResult = await landUiMeta(projectRoot);
10078
+ const bizResult = await landBizUiMeta(projectRoot, variant);
10079
+ record({
10080
+ name: "meta-landing",
10081
+ status: "ok",
10082
+ detail: `ui: ${uiResult.metaFilesWritten}/${uiResult.metaFilesTotal}, biz-ui: ${bizResult.metaFilesWritten}/${bizResult.metaFilesTotal}`
10083
+ });
10084
+ } catch (err) {
10085
+ recordFailure("meta-landing", err);
10086
+ }
10087
+ } else {
10088
+ record({ name: "meta-landing", status: "skip", detail: "aborted" });
10089
+ }
10090
+ if (!aborted) {
10091
+ try {
10092
+ const config = await readProjectConfig(projectRoot);
10093
+ if (config) {
10094
+ config.mode = "graft";
10095
+ config.legacyLib = legacyLib;
10096
+ await writeProjectConfig(projectRoot, config);
10097
+ record({ name: "config-mode", status: "ok", detail: `mode=graft, legacyLib=${legacyLib}` });
10098
+ } else {
10099
+ record({ name: "config-mode", status: "skip", detail: "no config.json found to patch" });
10100
+ }
10101
+ } catch (err) {
10102
+ recordFailure("config-mode", err);
10103
+ }
10104
+ } else {
10105
+ record({ name: "config-mode", status: "skip", detail: "aborted" });
10106
+ }
10107
+ if (!aborted) {
10108
+ try {
10109
+ const giPath = path44.join(projectRoot, ".gitignore");
10110
+ let giContent = "";
10111
+ try {
10112
+ giContent = await fsNode2.readFile(giPath, "utf-8");
10113
+ } catch {
10114
+ }
10115
+ if (giContent.includes(GITIGNORE_MARKER_START2)) {
10116
+ record({ name: "gitignore", status: "skip", detail: "teamix-evo markers already present" });
10117
+ } else {
10118
+ const block = [
10119
+ "",
10120
+ GITIGNORE_MARKER_START2,
10121
+ ...GITIGNORE_RULES2,
10122
+ GITIGNORE_MARKER_END2,
10123
+ ""
10124
+ ].join("\n");
10125
+ const separator = giContent.length > 0 && !giContent.endsWith("\n") ? "\n" : "";
10126
+ await fsNode2.writeFile(giPath, giContent + separator + block, "utf-8");
10127
+ record({
10128
+ name: "gitignore",
10129
+ status: "ok",
10130
+ detail: `${GITIGNORE_RULES2.filter((r) => r && !r.startsWith("#")).length} rules appended`
10131
+ });
10132
+ }
10133
+ } catch (err) {
10134
+ recordFailure("gitignore", err);
10135
+ }
10136
+ } else {
10137
+ record({ name: "gitignore", status: "skip", detail: "aborted" });
10138
+ }
10139
+ const status = steps.some((s) => s.status === "fail") ? "partial" : "success";
10140
+ return { status, steps };
10141
+ }
10142
+ function renderGraftManagedBody(legacyLibName, legacyImports) {
10143
+ return `## \u53CC\u6808\u7814\u53D1\u89C4\u5219
10144
+
10145
+ \u672C\u9879\u76EE\u540C\u65F6\u5B58\u5728 ${legacyLibName}\uFF08\u65E7\u6808\uFF09\u548C teamix-evo\uFF08\u65B0\u6808\uFF09\u4E24\u5957\u6280\u672F\u6808\u3002
10146
+
10147
+ ### \u5224\u65AD\u89C4\u5219\u2014\u2014\u901A\u8FC7 import \u8BED\u53E5\u8BC6\u522B
10148
+ - \u6587\u4EF6\u4E2D import \u4E86 ${legacyImports} \u2192 **\u65E7\u6808**\uFF0C\u6309 ${legacyLibName} \u89C4\u8303\u7814\u53D1\uFF0C**\u8DF3\u8FC7** teamix-evo \u7684 design / code skill
10149
+ - \u6587\u4EF6\u4E2D import \u4E86 \`@/components/ui\`\u3001\u4F7F\u7528 Tailwind class \u2192 **\u65B0\u6808**\uFF0C\u6B63\u5E38\u89E6\u53D1 teamix-evo design / code skill
10150
+ - \u65B0\u5EFA\u9875\u9762 \u2192 \u9ED8\u8BA4\u4F7F\u7528\u65B0\u6808\uFF08teamix-evo\uFF09
10151
+
10152
+ ### \u7981\u6B62\u4E8B\u9879
10153
+ - \u7981\u6B62\u5728\u65E7\u6808\u6587\u4EF6\u4E2D\u5F15\u5165 \`@/components/ui\` \u6216 Tailwind class
10154
+ - \u7981\u6B62\u5728\u65B0\u6808\u6587\u4EF6\u4E2D\u5F15\u5165 ${legacyImports}
10155
+ - \u7981\u6B62\u5728\u540C\u4E00\u6587\u4EF6\u4E2D\u6DF7\u7528\u4E24\u5957\u7EC4\u4EF6\u5E93`;
10156
+ }
10157
+ function wrapGraftManagedBlock(body) {
10158
+ return `<!-- teamix-evo:managed:start id="${AGENTS_MD_GRAFT_MANAGED_ID}" -->
10159
+ ${body}
10160
+ <!-- teamix-evo:managed:end id="${AGENTS_MD_GRAFT_MANAGED_ID}" -->`;
10161
+ }
10162
+
10163
+ // src/commands/graft/index.ts
10164
+ init_logger();
10165
+ init_error();
10166
+ init_fs();
10167
+ var APP_ENTRY_CANDIDATES = [
10168
+ "src/app.tsx",
10169
+ "src/app.ts",
10170
+ "src/app.jsx",
10171
+ "src/app.js",
10172
+ "src/index.tsx",
10173
+ "src/index.ts",
10174
+ "src/index.jsx",
10175
+ "src/index.js"
10176
+ ];
10177
+ var POSTCSS_CONFIG_CANDIDATES = [
10178
+ "postcss.config.js",
10179
+ "postcss.config.cjs",
10180
+ "postcss.config.mjs",
10181
+ "postcss.config.ts",
10182
+ ".postcssrc",
10183
+ ".postcssrc.json",
10184
+ ".postcssrc.yml",
10185
+ ".postcssrc.yaml",
10186
+ ".postcssrc.js"
10187
+ ];
10188
+ var CONFLICT_PATHS = [
10189
+ { path: ".teamix-evo", type: "directory" },
10190
+ { path: "src/components/ui", type: "directory" },
10191
+ { path: "src/components/business", type: "directory" },
10192
+ { path: "tokens", type: "directory" }
10193
+ ];
10194
+ async function findFirst(cwd, candidates) {
10195
+ for (const c of candidates) {
10196
+ if (await fileExists(path45.join(cwd, c))) return c;
10197
+ }
10198
+ return null;
10199
+ }
10200
+ async function getLegacyLibVersion(cwd, legacyLib) {
10201
+ const pkgRaw = await readFileOrNull(path45.join(cwd, "package.json"));
10202
+ if (!pkgRaw) return "unknown";
10203
+ try {
10204
+ const pkg = JSON.parse(pkgRaw);
10205
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
10206
+ const libKeyMap = {
10207
+ fusion: ["@alifd/next", "@ali/teamix-material"],
10208
+ antd: ["antd"],
10209
+ element: ["element-ui", "element-plus"]
10210
+ };
10211
+ const keys = libKeyMap[legacyLib] ?? [];
10212
+ for (const key of keys) {
10213
+ if (allDeps[key]) return allDeps[key];
10214
+ }
10215
+ } catch {
10216
+ }
10217
+ return "unknown";
10218
+ }
10219
+ async function detectConflicts(cwd) {
10220
+ const conflicts = [];
10221
+ for (const entry of CONFLICT_PATHS) {
10222
+ const full = path45.join(cwd, entry.path);
10223
+ try {
10224
+ const stat6 = await fs32.stat(full);
10225
+ if (entry.type === "directory" && stat6.isDirectory() || entry.type === "file" && stat6.isFile()) {
10226
+ conflicts.push(entry);
10227
+ }
10228
+ } catch {
10229
+ }
10230
+ }
10231
+ return conflicts;
10232
+ }
10233
+ async function analyzeProject(cwd) {
10234
+ const state = await detectProjectState(cwd);
10235
+ if (state.state !== "other") {
10236
+ assertCommandPrecondition("graft", state.state);
10237
+ throw new Error("unreachable");
10238
+ }
10239
+ const legacyLib = state.legacyLib ?? "unknown";
10240
+ const buildTool = state.buildTool ?? "unknown";
10241
+ const legacyVersion = await getLegacyLibVersion(cwd, legacyLib);
10242
+ const BUILD_TOOL_CONFIG_CANDIDATES = {
10243
+ ice: ["build.json"],
10244
+ vite: ["vite.config.ts", "vite.config.js", "vite.config.mts", "vite.config.mjs"],
10245
+ webpack: ["webpack.config.js", "webpack.config.ts", "webpack.config.cjs"]
10246
+ };
10247
+ const buildToolConfig = await findFirst(
10248
+ cwd,
10249
+ BUILD_TOOL_CONFIG_CANDIDATES[buildTool] ?? []
10250
+ );
10251
+ const postcssPath = await findFirst(cwd, POSTCSS_CONFIG_CANDIDATES);
10252
+ const appEntry = await findFirst(cwd, APP_ENTRY_CANDIDATES);
10253
+ const conflicts = await detectConflicts(cwd);
10254
+ return {
10255
+ report: {
10256
+ projectRoot: cwd,
10257
+ legacyLib: { name: legacyLib, version: legacyVersion },
10258
+ buildTool: { type: buildTool, configFile: buildToolConfig },
10259
+ postcssConfig: { exists: postcssPath !== null, path: postcssPath },
10260
+ appEntry,
10261
+ conflicts
10262
+ },
10263
+ legacyLib
10264
+ };
10265
+ }
10266
+ function printReport(report) {
10267
+ logger.info("Teamix Evo Graft \u2014 \u53CC\u6808\u5171\u5B58\u524D\u7F6E\u68C0\u67E5");
10268
+ logger.info("");
10269
+ logger.info(` \u9879\u76EE\u76EE\u5F55\uFF1A${report.projectRoot}`);
10270
+ logger.info(
10271
+ ` \u65E7\u7EC4\u4EF6\u5E93\uFF1A${report.legacyLib.name} (${report.legacyLib.version})`
10272
+ );
10273
+ logger.info(` \u6784\u5EFA\u5DE5\u5177\uFF1A${report.buildTool.type}`);
10274
+ logger.info(
10275
+ ` PostCSS \u914D\u7F6E\uFF1A${report.postcssConfig.path ?? "\u672A\u68C0\u6D4B\u5230"}`
10276
+ );
10277
+ logger.info(` App \u5165\u53E3\uFF1A${report.appEntry ?? "\u672A\u68C0\u6D4B\u5230"}`);
10278
+ if (report.conflicts.length > 0) {
10279
+ logger.info("");
10280
+ logger.warn(" \u5DF2\u5B58\u5728\u7684\u8DEF\u5F84\uFF08\u53EF\u80FD\u51B2\u7A81\uFF09\uFF1A");
10281
+ for (const c of report.conflicts) {
10282
+ logger.warn(` ${c.path} (${c.type})`);
10283
+ }
10284
+ }
10285
+ }
10286
+ var graftCommand = new Command39("graft").description(
10287
+ "\u53E0\u52A0 Teamix Evo AICoding \u80FD\u529B\u5230\u73B0\u6709\u9879\u76EE\uFF08\u53CC\u6808\u5171\u5B58\uFF0CADR 0047\uFF09"
10288
+ ).option("--variant <name>", "\u6307\u5B9A tokens variant\uFF08\u5982 opentrek\uFF09").option("--cwd <dir>", "\u6307\u5B9A\u5DE5\u7A0B\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4\uFF1A\u5F53\u524D\u76EE\u5F55\uFF09").option("--json", "\u8F93\u51FA JSON \u683C\u5F0F\u7684\u5206\u6790\u62A5\u544A\uFF08\u4F9B AI skill \u6D88\u8D39\uFF09").option("--apply", "\u6267\u884C graft pipeline\uFF08\u9ED8\u8BA4\u4EC5\u524D\u7F6E\u68C0\u67E5\uFF09").option("-y, --yes", "\u8DF3\u8FC7 --apply \u4E8C\u6B21\u786E\u8BA4").action(async (opts) => {
10289
+ const cwd = path45.resolve(opts.cwd ?? process.cwd());
10290
+ const apply = opts.apply ?? false;
10291
+ try {
10292
+ const { report, legacyLib } = await analyzeProject(cwd);
10293
+ if (opts.json) {
10294
+ console.log(JSON.stringify(report, null, 2));
10295
+ } else {
10296
+ printReport(report);
10297
+ }
10298
+ if (!apply) {
10299
+ if (!opts.json) {
10300
+ logger.info("");
10301
+ logger.info(
10302
+ "\u524D\u7F6E\u68C0\u67E5\u5B8C\u6210\u3002\u52A0 --apply --variant <v> \u6267\u884C graft pipeline\u3002"
10303
+ );
10304
+ }
10305
+ return;
10306
+ }
10307
+ if (!opts.variant) {
10308
+ logger.error("--apply \u9700\u8981\u6307\u5B9A --variant\uFF08\u5982 --variant opentrek\uFF09");
10309
+ process.exitCode = 1;
10310
+ return;
10311
+ }
10312
+ if (legacyLib === "unknown") {
10313
+ logger.error(
10314
+ "\u672A\u8BC6\u522B\u65E7\u7EC4\u4EF6\u5E93\u3002\u8BF7\u786E\u8BA4 package.json \u4E2D\u5305\u542B @alifd/next / antd / element-ui \u7B49\u4F9D\u8D56\u3002"
10315
+ );
10316
+ process.exitCode = 1;
10317
+ return;
10318
+ }
10319
+ const isInteractive = Boolean(process.stdin.isTTY);
10320
+ if (!opts.yes && isInteractive) {
10321
+ logger.info("");
10322
+ logger.info(
10323
+ `graft --apply \u5C06\u5B89\u88C5 teamix-evo \u5168\u6808\uFF08tokens + UI + biz-ui + skills + AGENTS.md\uFF09\uFF0Cvariant = "${opts.variant}"\u3002`
10324
+ );
10325
+ const confirmed = await prompts7.confirm({
10326
+ message: "\u7EE7\u7EED\u6267\u884C\uFF1F"
10327
+ });
10328
+ if (prompts7.isCancel(confirmed) || !confirmed) {
10329
+ logger.info("\u5DF2\u53D6\u6D88\u3002");
10330
+ return;
10331
+ }
10332
+ }
10333
+ logger.info("");
10334
+ logger.info("\u6267\u884C graft pipeline\u2026");
10335
+ logger.info("");
10336
+ const result = await runGraftInit({
10337
+ projectRoot: cwd,
10338
+ variant: opts.variant,
10339
+ legacyLib,
10340
+ onStep: (step) => {
10341
+ const icon = STEP_ICON[step.status];
10342
+ const detail = step.detail ? ` \u2014 ${step.detail}` : "";
10343
+ logger.info(` ${icon} ${step.name}${detail}`);
10344
+ }
10345
+ });
10346
+ logger.info("");
10347
+ if (result.status === "success") {
10348
+ logger.success(
10349
+ `graft \u5B8C\u6210\uFF08${result.steps.filter((s) => s.status === "ok").length}/${result.steps.length} \u6B65\u6210\u529F\uFF09`
10350
+ );
10351
+ } else {
10352
+ logger.warn("graft \u90E8\u5206\u5B8C\u6210\uFF08\u542B\u5931\u8D25\u6B65\u9AA4\uFF09\uFF0C\u8BE6\u89C1\u4E0A\u65B9\u660E\u7EC6\u3002");
10353
+ const failed = result.steps.filter((s) => s.status === "fail");
10354
+ for (const s of failed) {
10355
+ logger.error(` \u2716 ${s.name}: ${s.detail ?? "unknown error"}`);
10356
+ }
10357
+ process.exitCode = 1;
10358
+ }
10359
+ } catch (err) {
10360
+ logger.error(`graft \u5931\u8D25\uFF1A${getErrorMessage(err)}`);
10361
+ logger.debug(err.stack ?? "");
10362
+ process.exitCode = 1;
10363
+ }
10364
+ });
10365
+
9973
10366
  // src/commands/restore/index.ts
10367
+ import { Command as Command40 } from "commander";
10368
+ import * as path46 from "path";
10369
+ import * as prompts8 from "@clack/prompts";
9974
10370
  init_logger();
9975
10371
  init_error();
9976
10372
  function createRestoreCommand() {
9977
10373
  return new Command40("restore").description(
9978
10374
  "\u56DE\u6EDA .teamix-evo/ \u5230\u6307\u5B9A snapshot\uFF08init/update \u5931\u8D25\u65F6\u4F7F\u7528 \u2014 ADR 0019 \xA72\uFF09"
9979
10375
  ).argument("[ts]", "\u76EE\u6807 snapshot \u65F6\u95F4\u6233\uFF08\u5982 2026-06-11T20-59-03-000Z\uFF09").option("--list", "\u5217\u51FA\u53EF\u7528 snapshot\uFF08\u4E0D\u505A\u5B9E\u9645\u56DE\u6EDA\uFF09").option("--cwd <dir>", "\u6307\u5B9A\u5DE5\u7A0B\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4\uFF1A\u5F53\u524D\u76EE\u5F55\uFF09").option("-y, --yes", "\u8DF3\u8FC7\u4E8C\u6B21\u786E\u8BA4\uFF08destructive\uFF0C\u8BF7\u786E\u8BA4\u65E0\u8BEF\uFF09").action(async (ts, opts) => {
9980
- const cwd = path45.resolve(opts.cwd ?? process.cwd());
10376
+ const cwd = path46.resolve(opts.cwd ?? process.cwd());
9981
10377
  try {
9982
10378
  const snapshots = await listSnapshots(cwd);
9983
10379
  if (opts.list) {
@@ -10025,10 +10421,10 @@ function createRestoreCommand() {
10025
10421
  logger.info(
10026
10422
  '\u56DE\u6EDA\u524D\u4F1A\u81EA\u52A8\u518D\u505A\u4E00\u6B21 reason="restore" \u7684\u5B89\u5168 snapshot\uFF0C\u53EF\u4E8C\u6B21\u56DE\u6EDA\u3002'
10027
10423
  );
10028
- const confirmed = await prompts7.confirm({
10424
+ const confirmed = await prompts8.confirm({
10029
10425
  message: "\u7EE7\u7EED\u56DE\u6EDA\uFF1F"
10030
10426
  });
10031
- if (prompts7.isCancel(confirmed) || !confirmed) {
10427
+ if (prompts8.isCancel(confirmed) || !confirmed) {
10032
10428
  logger.info("\u5DF2\u53D6\u6D88\u3002");
10033
10429
  return;
10034
10430
  }
@@ -10074,12 +10470,12 @@ function printSnapshotTable(snapshots) {
10074
10470
 
10075
10471
  // src/commands/switch/index.ts
10076
10472
  import { Command as Command41 } from "commander";
10077
- import * as path47 from "path";
10078
- import * as prompts8 from "@clack/prompts";
10473
+ import * as path48 from "path";
10474
+ import * as prompts9 from "@clack/prompts";
10079
10475
 
10080
10476
  // src/core/variant-switch.ts
10081
10477
  init_fs();
10082
- import * as path46 from "path";
10478
+ import * as path47 from "path";
10083
10479
  import * as fs33 from "fs/promises";
10084
10480
  import {
10085
10481
  loadTokensPackageManifest as loadTokensPackageManifest3,
@@ -10117,8 +10513,8 @@ async function runVariantSwitch(options) {
10117
10513
  const upstreamByBasename = /* @__PURE__ */ new Map();
10118
10514
  for (const fileRel of variantEntry.files) {
10119
10515
  upstreamByBasename.set(
10120
- path46.basename(fileRel),
10121
- path46.join(packageRoot, fileRel)
10516
+ path47.basename(fileRel),
10517
+ path47.join(packageRoot, fileRel)
10122
10518
  );
10123
10519
  }
10124
10520
  const prior = await readInstalledManifest(projectRoot) ?? {
@@ -10132,7 +10528,7 @@ async function runVariantSwitch(options) {
10132
10528
  const priorVersion = installedIdx >= 0 ? prior.installed[installedIdx].version : "0.0.0";
10133
10529
  const changes = [];
10134
10530
  for (const resource of priorResources) {
10135
- const consumerBasename = path46.basename(resource.target);
10531
+ const consumerBasename = path47.basename(resource.target);
10136
10532
  const upstreamBasename = lookupUpstreamBasename2(consumerBasename);
10137
10533
  const upstreamAbs = upstreamBasename ? upstreamByBasename.get(upstreamBasename) : void 0;
10138
10534
  if (resource.strategy === "frozen") {
@@ -10206,8 +10602,8 @@ async function runVariantSwitch(options) {
10206
10602
  }
10207
10603
  const refreshedResources = [];
10208
10604
  for (const resource of priorResources) {
10209
- const consumerAbs = path46.isAbsolute(resource.target) ? resource.target : path46.join(projectRoot, resource.target);
10210
- const consumerBasename = path46.basename(resource.target);
10605
+ const consumerAbs = path47.isAbsolute(resource.target) ? resource.target : path47.join(projectRoot, resource.target);
10606
+ const consumerBasename = path47.basename(resource.target);
10211
10607
  const upstreamBasename = lookupUpstreamBasename2(consumerBasename);
10212
10608
  const upstreamAbs = upstreamBasename ? upstreamByBasename.get(upstreamBasename) : void 0;
10213
10609
  if (resource.strategy === "regenerable" && upstreamAbs) {
@@ -10253,7 +10649,7 @@ async function runVariantSwitch(options) {
10253
10649
  installedAt: now
10254
10650
  };
10255
10651
  await writeFileSafe(
10256
- path46.join(projectRoot, ".teamix-evo", "tokens-lock.json"),
10652
+ path47.join(projectRoot, ".teamix-evo", "tokens-lock.json"),
10257
10653
  JSON.stringify(lock, null, 2) + "\n"
10258
10654
  );
10259
10655
  logger.debug(
@@ -10373,7 +10769,7 @@ function createSwitchCommand() {
10373
10769
  return new Command41("switch").description(
10374
10770
  "variant \u5207\u6362\uFF1A\u5148\u5C55\u793A file-level diff\uFF0C--apply \u624D\u771F\u5199\uFF08ADR 0019 \xA7D3\uFF09"
10375
10771
  ).argument("<new-variant>", "\u76EE\u6807 variant id\uFF08\u5982 opentrek / uni-manager\uFF09").option("--cwd <dir>", "\u6307\u5B9A\u5DE5\u7A0B\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4\uFF1A\u5F53\u524D\u76EE\u5F55\uFF09").option("--apply", "\u771F\u6B63\u6267\u884C\u5207\u6362\uFF08\u9ED8\u8BA4 dry-run\uFF0C\u4EC5\u5C55\u793A\u8BA1\u5212\uFF09").option("-y, --yes", "\u8DF3\u8FC7 --apply \u4E8C\u6B21\u786E\u8BA4\uFF08destructive\uFF0C\u8BF7\u786E\u8BA4\u65E0\u8BEF\uFF09").action(async (newVariant, opts) => {
10376
- const cwd = path47.resolve(opts.cwd ?? process.cwd());
10772
+ const cwd = path48.resolve(opts.cwd ?? process.cwd());
10377
10773
  const apply = opts.apply ?? false;
10378
10774
  try {
10379
10775
  const plan = await runVariantSwitch({
@@ -10419,10 +10815,10 @@ function createSwitchCommand() {
10419
10815
  logger.info(
10420
10816
  '\u6267\u884C\u524D\u4F1A\u81EA\u52A8\u6355\u83B7 reason="switch" snapshot\uFF0C\u53EF\u901A\u8FC7 `teamix-evo restore <ts>` \u56DE\u6EDA\u3002'
10421
10817
  );
10422
- const confirmed = await prompts8.confirm({
10818
+ const confirmed = await prompts9.confirm({
10423
10819
  message: `\u7EE7\u7EED\u5207\u6362\u81F3 "${newVariant}"\uFF1F`
10424
10820
  });
10425
- if (prompts8.isCancel(confirmed) || !confirmed) {
10821
+ if (prompts9.isCancel(confirmed) || !confirmed) {
10426
10822
  logger.info("\u5DF2\u53D6\u6D88\u3002");
10427
10823
  return;
10428
10824
  }