teamix-evo 0.16.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
@@ -582,7 +582,7 @@ var init_registry = __esm({
582
582
  });
583
583
 
584
584
  // src/index.ts
585
- import { Command as Command41 } from "commander";
585
+ import { Command as Command42 } from "commander";
586
586
  import { createRequire as createRequire9 } from "module";
587
587
 
588
588
  // src/commands/tokens/index.ts
@@ -807,9 +807,9 @@ async function installSkills(options) {
807
807
  async function renderSkillFiles(skill, options) {
808
808
  const { data, packageRoot } = options;
809
809
  const sourceAbs = path7.resolve(packageRoot, skill.source);
810
- const stat5 = await fs6.stat(sourceAbs);
810
+ const stat6 = await fs6.stat(sourceAbs);
811
811
  const rendered = /* @__PURE__ */ new Map();
812
- if (stat5.isFile()) {
812
+ if (stat6.isFile()) {
813
813
  const content = await renderSkillContent(sourceAbs, skill, data);
814
814
  rendered.set("SKILL.md", content);
815
815
  return rendered;
@@ -1072,13 +1072,13 @@ async function pruneEmptyIdeSkillDirs(args) {
1072
1072
  }
1073
1073
  for (const name of entries) {
1074
1074
  const dir = path7.join(skillsRoot, name);
1075
- let stat5;
1075
+ let stat6;
1076
1076
  try {
1077
- stat5 = await fs6.stat(dir);
1077
+ stat6 = await fs6.stat(dir);
1078
1078
  } catch {
1079
1079
  continue;
1080
1080
  }
1081
- if (!stat5.isDirectory()) continue;
1081
+ if (!stat6.isDirectory()) continue;
1082
1082
  let children;
1083
1083
  try {
1084
1084
  children = await fs6.readdir(dir);
@@ -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
  }
@@ -5016,8 +5016,8 @@ async function runSkillsDoctor(options) {
5016
5016
  }
5017
5017
  async function dirExists(p2) {
5018
5018
  try {
5019
- const stat5 = await fs17.stat(p2);
5020
- return stat5.isDirectory();
5019
+ const stat6 = await fs17.stat(p2);
5020
+ return stat6.isDirectory();
5021
5021
  } catch {
5022
5022
  return false;
5023
5023
  }
@@ -6125,8 +6125,8 @@ function extractIds(pkg) {
6125
6125
  }
6126
6126
  async function directoryExists(p2) {
6127
6127
  try {
6128
- const stat5 = await fs22.stat(p2);
6129
- return stat5.isDirectory();
6128
+ const stat6 = await fs22.stat(p2);
6129
+ return stat6.isDirectory();
6130
6130
  } catch {
6131
6131
  return false;
6132
6132
  }
@@ -8548,13 +8548,44 @@ async function detectProjectState(cwd) {
8548
8548
  significantEntries: []
8549
8549
  };
8550
8550
  }
8551
+ let legacyLib = "unknown";
8552
+ let buildTool = "unknown";
8553
+ let allDeps = {};
8554
+ if (hasPackageJson2) {
8555
+ const pkgRaw = await readFileOrNull(path36.join(absCwd, "package.json"));
8556
+ if (pkgRaw) {
8557
+ try {
8558
+ const pkg = JSON.parse(pkgRaw);
8559
+ allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
8560
+ } catch {
8561
+ }
8562
+ }
8563
+ }
8564
+ if ("@alifd/next" in allDeps || "@ali/teamix-material" in allDeps) {
8565
+ legacyLib = "fusion";
8566
+ } else if ("antd" in allDeps) {
8567
+ legacyLib = "antd";
8568
+ } else if ("element-ui" in allDeps || "element-plus" in allDeps) {
8569
+ legacyLib = "element";
8570
+ }
8571
+ if (await fileExists(path36.join(absCwd, "build.json"))) {
8572
+ buildTool = "ice";
8573
+ } else if (await fileExists(path36.join(absCwd, "vite.config.ts")) || await fileExists(path36.join(absCwd, "vite.config.js")) || await fileExists(path36.join(absCwd, "vite.config.mts"))) {
8574
+ buildTool = "vite";
8575
+ } else if (await fileExists(path36.join(absCwd, "webpack.config.js")) || await fileExists(path36.join(absCwd, "webpack.config.ts"))) {
8576
+ buildTool = "webpack";
8577
+ } else if ("umi" in allDeps || "@umijs/max" in allDeps) {
8578
+ buildTool = "umi";
8579
+ }
8551
8580
  return {
8552
8581
  state: "other",
8553
8582
  cwd: absCwd,
8554
8583
  hasTeamixDir: false,
8555
8584
  hasPackageJson: hasPackageJson2,
8556
8585
  hasComponentsJson,
8557
- significantEntries: significant.slice(0, 20).sort()
8586
+ significantEntries: significant.slice(0, 20).sort(),
8587
+ legacyLib,
8588
+ buildTool
8558
8589
  };
8559
8590
  }
8560
8591
 
@@ -8563,7 +8594,8 @@ init_logger();
8563
8594
  var COMMAND_LABELS = {
8564
8595
  init: "\u521D\u59CB\u5316 Teamix Evo \u5957\u4EF6",
8565
8596
  migrate: "shadcn \u9879\u76EE\u8FC1\u79FB\u4E3A Teamix Evo \u5957\u4EF6",
8566
- update: "Teamix Evo \u5957\u4EF6\u66F4\u65B0"
8597
+ update: "Teamix Evo \u5957\u4EF6\u66F4\u65B0",
8598
+ graft: "\u53E0\u52A0 Teamix Evo \u80FD\u529B"
8567
8599
  };
8568
8600
  var STATE_LABELS = {
8569
8601
  empty: "\u7A7A\u76EE\u5F55",
@@ -8574,13 +8606,14 @@ var STATE_LABELS = {
8574
8606
  var VALID_STATES = {
8575
8607
  init: "empty",
8576
8608
  migrate: "shadcn",
8577
- update: "teamix-evo"
8609
+ update: "teamix-evo",
8610
+ graft: "other"
8578
8611
  };
8579
8612
  var STATE_TO_COMMAND = {
8580
8613
  empty: "init",
8581
8614
  shadcn: "migrate",
8582
8615
  "teamix-evo": "update",
8583
- other: null
8616
+ other: "graft"
8584
8617
  };
8585
8618
  function assertCommandPrecondition(command, state) {
8586
8619
  const expected = VALID_STATES[command];
@@ -8594,13 +8627,6 @@ function assertCommandPrecondition(command, state) {
8594
8627
  if (suggestion) {
8595
8628
  const suggestionLabel = COMMAND_LABELS[suggestion];
8596
8629
  logger.info(`\u5EFA\u8BAE\u4F7F\u7528\uFF1Ateamix-evo ${suggestion}\uFF08${suggestionLabel}\uFF09`);
8597
- } else {
8598
- logger.info(
8599
- "\u5F53\u524D\u9879\u76EE\u7C7B\u578B\u6682\u4E0D\u652F\u6301\u76F4\u63A5\u63A5\u5165\u3002"
8600
- );
8601
- logger.info(
8602
- "\u5EFA\u8BAE\uFF1A\u5148\u7528 teamix-evo init \u521D\u59CB\u5316 Teamix Evo \u5957\u4EF6\uFF08\u7A7A\u76EE\u5F55\uFF09\uFF0C\u7136\u540E\u5BF9\u65E7\u9879\u76EE\u8FDB\u884C\u91CD\u6784\u3002"
8603
- );
8604
8630
  }
8605
8631
  process.exitCode = 1;
8606
8632
  }
@@ -9482,7 +9508,7 @@ async function detectLintVersions(projectRoot) {
9482
9508
  const pkgJson = pkgJsonRaw ? JSON.parse(pkgJsonRaw) : null;
9483
9509
  const devDeps = pkgJson?.devDependencies ?? {};
9484
9510
  const deps = pkgJson?.dependencies ?? {};
9485
- const resolve12 = async (pkg) => {
9511
+ const resolve13 = async (pkg) => {
9486
9512
  const declared = devDeps[pkg] ?? deps[pkg] ?? null;
9487
9513
  if (!declared) return null;
9488
9514
  const installedPkgJson = await readFileOrNull(
@@ -9492,8 +9518,8 @@ async function detectLintVersions(projectRoot) {
9492
9518
  return { declared, installed };
9493
9519
  };
9494
9520
  const [eslintConfig, stylelintConfig] = await Promise.all([
9495
- resolve12(LINT_PACKAGES[0]),
9496
- resolve12(LINT_PACKAGES[1])
9521
+ resolve13(LINT_PACKAGES[0]),
9522
+ resolve13(LINT_PACKAGES[1])
9497
9523
  ]);
9498
9524
  return { eslintConfig, stylelintConfig };
9499
9525
  }
@@ -9659,11 +9685,16 @@ var migrateCommand = new Command38("migrate").description(
9659
9685
  }
9660
9686
  });
9661
9687
 
9662
- // src/commands/restore/index.ts
9688
+ // src/commands/graft/index.ts
9663
9689
  import { Command as Command39 } from "commander";
9664
- import * as path44 from "path";
9690
+ import * as path45 from "path";
9691
+ import * as fs32 from "fs/promises";
9665
9692
  import * as prompts7 from "@clack/prompts";
9666
9693
 
9694
+ // src/core/graft-init.ts
9695
+ import { hasManagedRegion as hasManagedRegion5, replaceManagedRegion as replaceManagedRegion4 } from "@teamix-evo/registry";
9696
+ init_state();
9697
+
9667
9698
  // src/core/snapshot.ts
9668
9699
  init_logger();
9669
9700
  import * as fs31 from "fs/promises";
@@ -9672,6 +9703,7 @@ var TEAMIX_DIR6 = ".teamix-evo";
9672
9703
  var SNAPSHOTS_DIR = ".snapshots";
9673
9704
  var META_FILE = "_meta.json";
9674
9705
  var DEFAULT_KEEP = 5;
9706
+ var SNAPSHOT_REASONS = ["init", "update", "switch", "restore", "graft", "manual"];
9675
9707
  function isoToFsSafe3(iso) {
9676
9708
  return iso.replace(/[:.]/g, "-");
9677
9709
  }
@@ -9684,8 +9716,8 @@ function fsSafeToIso(safe) {
9684
9716
  async function createSnapshot(projectRoot, opts = {}) {
9685
9717
  const teamixDir = path43.join(projectRoot, TEAMIX_DIR6);
9686
9718
  try {
9687
- const stat5 = await fs31.stat(teamixDir);
9688
- if (!stat5.isDirectory()) return null;
9719
+ const stat6 = await fs31.stat(teamixDir);
9720
+ if (!stat6.isDirectory()) return null;
9689
9721
  } catch (err) {
9690
9722
  if (err.code === "ENOENT") return null;
9691
9723
  throw err;
@@ -9737,7 +9769,7 @@ async function listSnapshots(projectRoot) {
9737
9769
  const raw = await fs31.readFile(path43.join(dir, META_FILE), "utf-8");
9738
9770
  const parsed = JSON.parse(raw);
9739
9771
  if (typeof parsed.ts === "string") isoTs = parsed.ts;
9740
- if (typeof parsed.reason === "string" && ["init", "update", "switch", "restore", "manual"].includes(
9772
+ if (typeof parsed.reason === "string" && SNAPSHOT_REASONS.includes(
9741
9773
  parsed.reason
9742
9774
  )) {
9743
9775
  reason = parsed.reason;
@@ -9769,8 +9801,8 @@ async function restoreSnapshot(projectRoot, ts) {
9769
9801
  const snapshotRoot = path43.join(projectRoot, TEAMIX_DIR6, SNAPSHOTS_DIR);
9770
9802
  const target = path43.join(snapshotRoot, ts);
9771
9803
  try {
9772
- const stat5 = await fs31.stat(target);
9773
- if (!stat5.isDirectory()) {
9804
+ const stat6 = await fs31.stat(target);
9805
+ if (!stat6.isDirectory()) {
9774
9806
  throw new Error(`Snapshot path is not a directory: ${target}`);
9775
9807
  }
9776
9808
  } catch (err) {
@@ -9801,14 +9833,547 @@ async function restoreSnapshot(projectRoot, ts) {
9801
9833
  logger.debug(`Restored .teamix-evo/ from snapshot ${ts}`);
9802
9834
  }
9803
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
+
9804
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";
9805
10370
  init_logger();
9806
10371
  init_error();
9807
10372
  function createRestoreCommand() {
9808
- return new Command39("restore").description(
10373
+ return new Command40("restore").description(
9809
10374
  "\u56DE\u6EDA .teamix-evo/ \u5230\u6307\u5B9A snapshot\uFF08init/update \u5931\u8D25\u65F6\u4F7F\u7528 \u2014 ADR 0019 \xA72\uFF09"
9810
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) => {
9811
- const cwd = path44.resolve(opts.cwd ?? process.cwd());
10376
+ const cwd = path46.resolve(opts.cwd ?? process.cwd());
9812
10377
  try {
9813
10378
  const snapshots = await listSnapshots(cwd);
9814
10379
  if (opts.list) {
@@ -9856,10 +10421,10 @@ function createRestoreCommand() {
9856
10421
  logger.info(
9857
10422
  '\u56DE\u6EDA\u524D\u4F1A\u81EA\u52A8\u518D\u505A\u4E00\u6B21 reason="restore" \u7684\u5B89\u5168 snapshot\uFF0C\u53EF\u4E8C\u6B21\u56DE\u6EDA\u3002'
9858
10423
  );
9859
- const confirmed = await prompts7.confirm({
10424
+ const confirmed = await prompts8.confirm({
9860
10425
  message: "\u7EE7\u7EED\u56DE\u6EDA\uFF1F"
9861
10426
  });
9862
- if (prompts7.isCancel(confirmed) || !confirmed) {
10427
+ if (prompts8.isCancel(confirmed) || !confirmed) {
9863
10428
  logger.info("\u5DF2\u53D6\u6D88\u3002");
9864
10429
  return;
9865
10430
  }
@@ -9904,14 +10469,14 @@ function printSnapshotTable(snapshots) {
9904
10469
  }
9905
10470
 
9906
10471
  // src/commands/switch/index.ts
9907
- import { Command as Command40 } from "commander";
9908
- import * as path46 from "path";
9909
- import * as prompts8 from "@clack/prompts";
10472
+ import { Command as Command41 } from "commander";
10473
+ import * as path48 from "path";
10474
+ import * as prompts9 from "@clack/prompts";
9910
10475
 
9911
10476
  // src/core/variant-switch.ts
9912
10477
  init_fs();
9913
- import * as path45 from "path";
9914
- import * as fs32 from "fs/promises";
10478
+ import * as path47 from "path";
10479
+ import * as fs33 from "fs/promises";
9915
10480
  import {
9916
10481
  loadTokensPackageManifest as loadTokensPackageManifest3,
9917
10482
  getVariantEntry as getVariantEntry3
@@ -9948,8 +10513,8 @@ async function runVariantSwitch(options) {
9948
10513
  const upstreamByBasename = /* @__PURE__ */ new Map();
9949
10514
  for (const fileRel of variantEntry.files) {
9950
10515
  upstreamByBasename.set(
9951
- path45.basename(fileRel),
9952
- path45.join(packageRoot, fileRel)
10516
+ path47.basename(fileRel),
10517
+ path47.join(packageRoot, fileRel)
9953
10518
  );
9954
10519
  }
9955
10520
  const prior = await readInstalledManifest(projectRoot) ?? {
@@ -9963,7 +10528,7 @@ async function runVariantSwitch(options) {
9963
10528
  const priorVersion = installedIdx >= 0 ? prior.installed[installedIdx].version : "0.0.0";
9964
10529
  const changes = [];
9965
10530
  for (const resource of priorResources) {
9966
- const consumerBasename = path45.basename(resource.target);
10531
+ const consumerBasename = path47.basename(resource.target);
9967
10532
  const upstreamBasename = lookupUpstreamBasename2(consumerBasename);
9968
10533
  const upstreamAbs = upstreamBasename ? upstreamByBasename.get(upstreamBasename) : void 0;
9969
10534
  if (resource.strategy === "frozen") {
@@ -9984,7 +10549,7 @@ async function runVariantSwitch(options) {
9984
10549
  });
9985
10550
  continue;
9986
10551
  }
9987
- const upstreamContent = await fs32.readFile(upstreamAbs, "utf-8");
10552
+ const upstreamContent = await fs33.readFile(upstreamAbs, "utf-8");
9988
10553
  if (resource.strategy === "regenerable") {
9989
10554
  const newHash = computeHash(upstreamContent);
9990
10555
  if (newHash === resource.hash) {
@@ -10037,12 +10602,12 @@ async function runVariantSwitch(options) {
10037
10602
  }
10038
10603
  const refreshedResources = [];
10039
10604
  for (const resource of priorResources) {
10040
- const consumerAbs = path45.isAbsolute(resource.target) ? resource.target : path45.join(projectRoot, resource.target);
10041
- const consumerBasename = path45.basename(resource.target);
10605
+ const consumerAbs = path47.isAbsolute(resource.target) ? resource.target : path47.join(projectRoot, resource.target);
10606
+ const consumerBasename = path47.basename(resource.target);
10042
10607
  const upstreamBasename = lookupUpstreamBasename2(consumerBasename);
10043
10608
  const upstreamAbs = upstreamBasename ? upstreamByBasename.get(upstreamBasename) : void 0;
10044
10609
  if (resource.strategy === "regenerable" && upstreamAbs) {
10045
- const upstreamContent = await fs32.readFile(upstreamAbs, "utf-8");
10610
+ const upstreamContent = await fs33.readFile(upstreamAbs, "utf-8");
10046
10611
  await writeFileSafe(consumerAbs, upstreamContent);
10047
10612
  logger.debug(`[variant-switch] rewrite regenerable: ${resource.target}`);
10048
10613
  refreshedResources.push({
@@ -10052,8 +10617,8 @@ async function runVariantSwitch(options) {
10052
10617
  continue;
10053
10618
  }
10054
10619
  if (resource.strategy === "managed" && upstreamAbs && await fileExists(consumerAbs)) {
10055
- const upstreamContent = await fs32.readFile(upstreamAbs, "utf-8");
10056
- const consumerContent = await fs32.readFile(consumerAbs, "utf-8");
10620
+ const upstreamContent = await fs33.readFile(upstreamAbs, "utf-8");
10621
+ const consumerContent = await fs33.readFile(consumerAbs, "utf-8");
10057
10622
  const merged = mergeManagedRegions(upstreamContent, consumerContent);
10058
10623
  if (merged !== consumerContent) {
10059
10624
  await writeFileSafe(consumerAbs, merged);
@@ -10084,7 +10649,7 @@ async function runVariantSwitch(options) {
10084
10649
  installedAt: now
10085
10650
  };
10086
10651
  await writeFileSafe(
10087
- path45.join(projectRoot, ".teamix-evo", "tokens-lock.json"),
10652
+ path47.join(projectRoot, ".teamix-evo", "tokens-lock.json"),
10088
10653
  JSON.stringify(lock, null, 2) + "\n"
10089
10654
  );
10090
10655
  logger.debug(
@@ -10201,10 +10766,10 @@ var KIND_LABEL = {
10201
10766
  unchanged: "unchanged"
10202
10767
  };
10203
10768
  function createSwitchCommand() {
10204
- return new Command40("switch").description(
10769
+ return new Command41("switch").description(
10205
10770
  "variant \u5207\u6362\uFF1A\u5148\u5C55\u793A file-level diff\uFF0C--apply \u624D\u771F\u5199\uFF08ADR 0019 \xA7D3\uFF09"
10206
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) => {
10207
- const cwd = path46.resolve(opts.cwd ?? process.cwd());
10772
+ const cwd = path48.resolve(opts.cwd ?? process.cwd());
10208
10773
  const apply = opts.apply ?? false;
10209
10774
  try {
10210
10775
  const plan = await runVariantSwitch({
@@ -10250,10 +10815,10 @@ function createSwitchCommand() {
10250
10815
  logger.info(
10251
10816
  '\u6267\u884C\u524D\u4F1A\u81EA\u52A8\u6355\u83B7 reason="switch" snapshot\uFF0C\u53EF\u901A\u8FC7 `teamix-evo restore <ts>` \u56DE\u6EDA\u3002'
10252
10817
  );
10253
- const confirmed = await prompts8.confirm({
10818
+ const confirmed = await prompts9.confirm({
10254
10819
  message: `\u7EE7\u7EED\u5207\u6362\u81F3 "${newVariant}"\uFF1F`
10255
10820
  });
10256
- if (prompts8.isCancel(confirmed) || !confirmed) {
10821
+ if (prompts9.isCancel(confirmed) || !confirmed) {
10257
10822
  logger.info("\u5DF2\u53D6\u6D88\u3002");
10258
10823
  return;
10259
10824
  }
@@ -10320,7 +10885,7 @@ function printChangePlan(from, to, toVersion, changes) {
10320
10885
  // src/index.ts
10321
10886
  var require9 = createRequire9(import.meta.url);
10322
10887
  var { version } = require9("../package.json");
10323
- var program = new Command41();
10888
+ var program = new Command42();
10324
10889
  program.name("teamix-evo").description("Where ideas evolve. \u2014 AI Coding \u5957\u4EF6").version(version);
10325
10890
  program.addCommand(tokensCommand);
10326
10891
  program.addCommand(skillsCommand);
@@ -10331,6 +10896,7 @@ program.addCommand(lintCommand);
10331
10896
  program.addCommand(initCommand5);
10332
10897
  program.addCommand(updateCommand5);
10333
10898
  program.addCommand(migrateCommand);
10899
+ program.addCommand(graftCommand);
10334
10900
  program.addCommand(restoreCommand);
10335
10901
  program.addCommand(switchCommand);
10336
10902
  function enableHelpAfterError(cmd) {