teamix-evo 0.5.0 → 0.6.1

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
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command29 } from "commander";
5
- import { createRequire as createRequire7 } from "module";
4
+ import { Command as Command32 } from "commander";
5
+ import { createRequire as createRequire8 } from "module";
6
6
 
7
7
  // src/commands/tokens/index.ts
8
8
  import { Command as Command6 } from "commander";
@@ -529,9 +529,11 @@ function makeMirrorRecord(skill, targetAbs, content, ide, scope, rel2) {
529
529
  }
530
530
  async function updateSkills(options) {
531
531
  const { manifest, ides, scope, projectRoot } = options;
532
+ const idFilter = options.onlyIds ? new Set(options.onlyIds) : null;
532
533
  const summary = { overwritten: 0, managed: 0, skipped: 0, created: 0 };
533
534
  const updated = [];
534
535
  for (const skill of manifest.skills) {
536
+ if (idFilter && !idFilter.has(skill.id)) continue;
535
537
  const skillIdes = skill.ides.filter((i) => ides.includes(i));
536
538
  if (skillIdes.length === 0) continue;
537
539
  const sourceRecords = await rewriteSkillSource(
@@ -733,11 +735,73 @@ async function ensureMcpJson(projectRoot) {
733
735
  // src/core/skills-add.ts
734
736
  var DEFAULT_SKILLS_PACKAGE = "@teamix-evo/skills";
735
737
  var FLAT_VARIANT = "_flat";
738
+ async function runSkillsInit(options) {
739
+ const { projectRoot } = options;
740
+ const packageName = options.packageName ?? DEFAULT_SKILLS_PACKAGE;
741
+ const ides = [...options.ides];
742
+ const scope = options.scope;
743
+ if (ides.length === 0) {
744
+ throw new Error("At least one IDE must be selected.");
745
+ }
746
+ await ensureTeamixDir(projectRoot);
747
+ const existingConfig = await readProjectConfig(projectRoot);
748
+ const existingSkillsCfg = existingConfig?.packages?.skills;
749
+ const { manifest, data, packageRoot } = await loadSkillsData(packageName);
750
+ const currentTokensVariant = await readTokensVariant(projectRoot);
751
+ const existing = await readExistingState(projectRoot, packageName);
752
+ const candidateIds = manifest.skills.filter((s) => {
753
+ const effectiveScope = s.scope ?? "project";
754
+ if (effectiveScope !== scope) {
755
+ logger.debug(
756
+ `Skipping skill "${s.id}" (scope=${effectiveScope}): current install scope is "${scope}". Use \`skills add ${s.id} --scope ${effectiveScope}\` to install.`
757
+ );
758
+ return false;
759
+ }
760
+ if (!s.variant) return true;
761
+ if (!currentTokensVariant) {
762
+ logger.debug(
763
+ `Skipping variant-bound skill "${s.id}" (variant=${s.variant}): no tokens variant installed; will be picked up when "tokens init" runs.`
764
+ );
765
+ return false;
766
+ }
767
+ if (s.variant !== currentTokensVariant) {
768
+ logger.debug(
769
+ `Skipping variant-bound skill "${s.id}" (variant=${s.variant}): current tokens variant is "${currentTokensVariant}".`
770
+ );
771
+ return false;
772
+ }
773
+ return true;
774
+ }).map((s) => s.id);
775
+ const skippedSkillIds = candidateIds.filter(
776
+ (id) => existing.skillIds.has(id)
777
+ );
778
+ const onlyIds = candidateIds.filter((id) => !existing.skillIds.has(id));
779
+ if (existingSkillsCfg && onlyIds.length === 0) {
780
+ return { status: "already-initialized" };
781
+ }
782
+ return finalizeSkillsInstall({
783
+ projectRoot,
784
+ packageName,
785
+ ideIdent: options.ide ?? "qoder",
786
+ manifest,
787
+ data,
788
+ packageRoot,
789
+ ides,
790
+ scope,
791
+ onlyIds,
792
+ skippedSkillIds,
793
+ existing,
794
+ existingConfig
795
+ });
796
+ }
736
797
  async function runSkillsAdd(options) {
798
+ if (!options.names || options.names.length === 0) {
799
+ throw new Error(
800
+ "runSkillsAdd requires at least one skill id. Use runSkillsInit() for bulk install."
801
+ );
802
+ }
737
803
  const { projectRoot, names: requestedNames } = options;
738
804
  const packageName = options.packageName ?? DEFAULT_SKILLS_PACKAGE;
739
- const ideIdent = options.ide ?? "qoder";
740
- const isIncremental = !!requestedNames && requestedNames.length > 0;
741
805
  await ensureTeamixDir(projectRoot);
742
806
  const existingConfig = await readProjectConfig(projectRoot);
743
807
  const existingSkillsCfg = existingConfig?.packages?.skills;
@@ -750,57 +814,27 @@ async function runSkillsAdd(options) {
750
814
  throw new Error("Scope must be specified (project | global).");
751
815
  }
752
816
  const { manifest, data, packageRoot } = await loadSkillsData(packageName);
753
- const currentTokensVariant = await readTokensVariant(projectRoot);
754
- if (isIncremental) {
755
- const known = new Set(manifest.skills.map((s) => s.id));
756
- const unknown = requestedNames.filter((n) => !known.has(n));
757
- if (unknown.length > 0) {
758
- const available = [...known].join(", ");
759
- throw new Error(
760
- `Unknown skill id(s): ${unknown.join(", ")}. Available: ${available || "(none)"}.`
817
+ const known = new Set(manifest.skills.map((s) => s.id));
818
+ const unknown = requestedNames.filter((n) => !known.has(n));
819
+ if (unknown.length > 0) {
820
+ const available = [...known].join(", ");
821
+ throw new Error(
822
+ `Unknown skill id(s): ${unknown.join(", ")}. Available: ${available || "(none)"}.`
823
+ );
824
+ }
825
+ for (const s of manifest.skills) {
826
+ if (requestedNames.includes(s.id) && s.scope && s.scope !== scope) {
827
+ logger.warn(
828
+ `"${s.id}" \u63A8\u8350 ${s.scope} scope \u5B89\u88C5\u3002\u5F53\u524D\u4EE5 ${scope} scope \u5F3A\u5236\u5B89\u88C5,\u53EF\u80FD\u4E0E\u53E6\u4E00 scope \u7684\u526F\u672C\u51B2\u7A81\u3002\u5EFA\u8BAE\u6539\u7528 \`skills add ${s.id} --scope ${s.scope}\`\u3002`
761
829
  );
762
830
  }
763
831
  }
764
- const existingInstalled = await readInstalledManifest(projectRoot);
765
- const existingPkg = existingInstalled?.installed.find(
766
- (p) => p.package === packageName
832
+ const existing = await readExistingState(projectRoot, packageName);
833
+ const skippedSkillIds = requestedNames.filter(
834
+ (n) => existing.skillIds.has(n)
767
835
  );
768
- const existingLock = await readSkillsLock(projectRoot);
769
- const existingSkillIds = /* @__PURE__ */ new Set([
770
- ...Object.keys(existingLock?.skills ?? {}),
771
- // Legacy fallback: pre-ADR-0013 installs only had manifest.json. Derive
772
- // skill ids by stripping the trailing :source / :sub-file suffix.
773
- ...(existingPkg?.resources ?? []).map((r) => r.id.split(":")[0])
774
- ]);
775
- let onlyIds;
776
- let skippedSkillIds;
777
- if (isIncremental) {
778
- skippedSkillIds = requestedNames.filter((n) => existingSkillIds.has(n));
779
- onlyIds = requestedNames.filter((n) => !existingSkillIds.has(n));
780
- } else {
781
- const candidateIds = manifest.skills.filter((s) => {
782
- if (!s.variant) return true;
783
- if (!currentTokensVariant) {
784
- logger.debug(
785
- `Skipping variant-bound skill "${s.id}" (variant=${s.variant}): no tokens variant installed; will be picked up when "tokens init" runs.`
786
- );
787
- return false;
788
- }
789
- if (s.variant !== currentTokensVariant) {
790
- logger.debug(
791
- `Skipping variant-bound skill "${s.id}" (variant=${s.variant}): current tokens variant is "${currentTokensVariant}".`
792
- );
793
- return false;
794
- }
795
- return true;
796
- }).map((s) => s.id);
797
- skippedSkillIds = candidateIds.filter((id) => existingSkillIds.has(id));
798
- onlyIds = candidateIds.filter((id) => !existingSkillIds.has(id));
799
- }
800
- if (!isIncremental && existingSkillsCfg && onlyIds.length === 0) {
801
- return { status: "already-added" };
802
- }
803
- if (isIncremental && onlyIds.length === 0) {
836
+ const onlyIds = requestedNames.filter((n) => !existing.skillIds.has(n));
837
+ if (onlyIds.length === 0) {
804
838
  return {
805
839
  status: "installed",
806
840
  packageName,
@@ -814,6 +848,48 @@ async function runSkillsAdd(options) {
814
848
  skippedSkillIds
815
849
  };
816
850
  }
851
+ return finalizeSkillsInstall({
852
+ projectRoot,
853
+ packageName,
854
+ ideIdent: options.ide ?? "qoder",
855
+ manifest,
856
+ data,
857
+ packageRoot,
858
+ ides,
859
+ scope,
860
+ onlyIds,
861
+ skippedSkillIds,
862
+ existing,
863
+ existingConfig
864
+ });
865
+ }
866
+ async function readExistingState(projectRoot, packageName) {
867
+ const installed = await readInstalledManifest(projectRoot);
868
+ const pkg = installed?.installed.find((p) => p.package === packageName);
869
+ const lock = await readSkillsLock(projectRoot);
870
+ const skillIds = /* @__PURE__ */ new Set([
871
+ ...Object.keys(lock?.skills ?? {}),
872
+ // Legacy fallback: pre-ADR-0013 installs only had manifest.json. Derive
873
+ // skill ids by stripping the trailing :source / :sub-file suffix.
874
+ ...(pkg?.resources ?? []).map((r) => r.id.split(":")[0] ?? r.id)
875
+ ]);
876
+ return { installed, pkg, lock, skillIds };
877
+ }
878
+ async function finalizeSkillsInstall(args) {
879
+ const {
880
+ projectRoot,
881
+ packageName,
882
+ ideIdent,
883
+ manifest,
884
+ data,
885
+ packageRoot,
886
+ ides,
887
+ scope,
888
+ onlyIds,
889
+ skippedSkillIds,
890
+ existing,
891
+ existingConfig
892
+ } = args;
817
893
  const result = await installSkills({
818
894
  projectRoot,
819
895
  manifest,
@@ -837,7 +913,7 @@ async function runSkillsAdd(options) {
837
913
  };
838
914
  await writeProjectConfig(projectRoot, config);
839
915
  const installedAt = (/* @__PURE__ */ new Date()).toISOString();
840
- const installedManifest = existingInstalled ?? {
916
+ const installedManifest = existing.installed ?? {
841
917
  schemaVersion: 1,
842
918
  installed: []
843
919
  };
@@ -845,7 +921,7 @@ async function runSkillsAdd(options) {
845
921
  (p) => p.package === packageName
846
922
  );
847
923
  const mergedResources = mergeInstalledResources(
848
- existingPkg?.resources ?? [],
924
+ existing.pkg?.resources ?? [],
849
925
  result.resources
850
926
  );
851
927
  const entry = {
@@ -858,7 +934,7 @@ async function runSkillsAdd(options) {
858
934
  if (idx >= 0) installedManifest.installed[idx] = entry;
859
935
  else installedManifest.installed.push(entry);
860
936
  await writeInstalledManifest(projectRoot, installedManifest);
861
- const lock = existingLock ?? {
937
+ const lock = existing.lock ?? {
862
938
  schemaVersion: 1,
863
939
  skills: {}
864
940
  };
@@ -1521,11 +1597,11 @@ var uninstallCommand = new Command5("uninstall").description(
1521
1597
  `Will remove ${removable.length} file(s); keep ${kept} managed file(s).`
1522
1598
  );
1523
1599
  if (!opts.yes) {
1524
- const confirm4 = await prompts.confirm({
1600
+ const confirm5 = await prompts.confirm({
1525
1601
  message: "\u786E\u8BA4\u5378\u8F7D tokens \u53D8\u4F53\uFF1F",
1526
1602
  initialValue: false
1527
1603
  });
1528
- if (prompts.isCancel(confirm4) || !confirm4) {
1604
+ if (prompts.isCancel(confirm5) || !confirm5) {
1529
1605
  logger.info("Cancelled.");
1530
1606
  return;
1531
1607
  }
@@ -1588,28 +1664,133 @@ tokensCommand.addCommand(listVariantsCommand);
1588
1664
  tokensCommand.addCommand(uninstallCommand);
1589
1665
 
1590
1666
  // src/commands/skills/index.ts
1591
- import { Command as Command13 } from "commander";
1667
+ import { Command as Command14 } from "commander";
1592
1668
 
1593
- // src/commands/skills/add.ts
1669
+ // src/commands/skills/init.ts
1594
1670
  import { Command as Command7 } from "commander";
1595
1671
  import * as prompts2 from "@clack/prompts";
1596
- var addCommand = new Command7("add").description(
1597
- "\u5411\u9879\u76EE\uFF08\u6216\u5168\u5C40 IDE \u914D\u7F6E\uFF09\u6DFB\u52A0 teamix-evo skills\uFF1B\u4E0D\u4F20 names \u5219\u6DFB\u52A0 manifest \u5185\u5168\u90E8 skill"
1598
- ).argument(
1599
- "[names...]",
1600
- "\u53EF\u9009\uFF1A\u4EC5\u6DFB\u52A0\u6307\u5B9A skill id\uFF08\u589E\u91CF\u6A21\u5F0F\uFF09\uFF1B\u7701\u7565\u5219\u6DFB\u52A0\u5168\u90E8"
1601
- ).option("--ide <list>", '\u9017\u53F7\u5206\u9694\u7684 IDE \u5217\u8868\uFF0C\u5982 "qoder,claude"').option(
1672
+ var initCommand2 = new Command7("init").description(
1673
+ "\u81EA\u4E3E teamix-evo skills\uFF08\u6309 tokens variant + scope \u5168\u88C5\u7B26\u5408\u6761\u4EF6\u7684 skill\uFF1Bscope \u4E3A global-only \u7684 entry skill \u81EA\u52A8\u8DF3\u8FC7 \u2014 ADR 0033\uFF09"
1674
+ ).option("--ide <list>", '\u9017\u53F7\u5206\u9694\u7684 IDE \u5217\u8868\uFF0C\u5982 "qoder,claude"').option("--scope <scope>", "project | global\uFF08\u9ED8\u8BA4 project\uFF09").option("-y, --yes", "\u4F7F\u7528\u9ED8\u8BA4\u503C\uFF0C\u8DF3\u8FC7\u4EA4\u4E92").action(async (opts) => {
1675
+ try {
1676
+ const ide = detectIde();
1677
+ const cwd = ide.getProjectRoot();
1678
+ const { ides, scope } = await resolveIdesAndScope({ opts });
1679
+ let projectRoot = cwd;
1680
+ if (scope === "global" && !isTeamixEvoProject(cwd)) {
1681
+ projectRoot = await ensureGlobalMetaRoot();
1682
+ logger.info(`Global skill install \u2014 meta root: ${projectRoot}`);
1683
+ } else if (scope !== "global" && !hasPackageJson(cwd)) {
1684
+ logger.error(
1685
+ "No package.json found in current directory. Please run this command in a valid project root."
1686
+ );
1687
+ process.exit(1);
1688
+ }
1689
+ logger.info(
1690
+ `Initializing skills (bulk): ides=[${ides.join(",")}], scope="${scope}"`
1691
+ );
1692
+ logger.debug(`Project root: ${projectRoot}`);
1693
+ const result = await runSkillsInit({
1694
+ projectRoot,
1695
+ ides,
1696
+ scope,
1697
+ ide: ide.name
1698
+ });
1699
+ if (result.status === "already-initialized") {
1700
+ logger.warn(
1701
+ `Skills already initialized. Use "teamix-evo skills add <name>" to add specific skills, "teamix-evo skills update" to refresh, or "teamix-evo skills uninstall" to remove.`
1702
+ );
1703
+ return;
1704
+ }
1705
+ logger.success(`Skills initialized: ${result.skillCount} skill(s)`);
1706
+ logger.info(` IDEs: ${result.ides.join(", ")}`);
1707
+ logger.info(` Scope: ${result.scope}`);
1708
+ if (result.addedSkillIds.length > 0) {
1709
+ logger.info(` Added: ${result.addedSkillIds.join(", ")}`);
1710
+ }
1711
+ if (result.skippedSkillIds.length > 0) {
1712
+ logger.info(
1713
+ ` Skipped: ${result.skippedSkillIds.join(", ")} (already added)`
1714
+ );
1715
+ }
1716
+ logger.info(` Files: ${result.fileCount}`);
1717
+ logger.info("");
1718
+ logger.info('Run "teamix-evo skills list" to see installed skills.');
1719
+ } catch (err) {
1720
+ logger.error(`Failed to init skills: ${err.message}`);
1721
+ logger.debug(err.stack ?? "");
1722
+ process.exitCode = 1;
1723
+ }
1724
+ });
1725
+ async function resolveIdesAndScope(args) {
1726
+ const { opts } = args;
1727
+ const isInteractive = Boolean(process.stdin.isTTY);
1728
+ if (opts.ide || opts.yes || !isInteractive) {
1729
+ const ides = opts.ide ? parseIdeList(opts.ide) : [...ALL_IDE_KINDS];
1730
+ const scope = parseScope(opts.scope);
1731
+ if (ides.length === 0) {
1732
+ throw new Error("At least one IDE must be selected.");
1733
+ }
1734
+ return { ides, scope };
1735
+ }
1736
+ const idesAns = await prompts2.multiselect({
1737
+ message: "\u9009\u62E9\u8981\u6CE8\u5165\u6280\u80FD\u7684 AI IDE\uFF08\u81F3\u5C11\u4E00\u4E2A\uFF09",
1738
+ options: ALL_IDE_KINDS.map((k) => ({
1739
+ value: k,
1740
+ label: k === "qoder" ? "Qoder" : "Claude Code"
1741
+ })),
1742
+ initialValues: [...ALL_IDE_KINDS],
1743
+ required: true
1744
+ });
1745
+ if (prompts2.isCancel(idesAns)) {
1746
+ throw new Error("Cancelled by user.");
1747
+ }
1748
+ const scopeAns = await prompts2.select({
1749
+ message: "\u5B89\u88C5\u8303\u56F4\uFF1F",
1750
+ options: [
1751
+ { value: "project", label: "\u9879\u76EE\u7EA7\uFF08.qoder/.claude \u5728\u5F53\u524D\u9879\u76EE\uFF09" },
1752
+ { value: "global", label: "\u5168\u5C40\uFF08~/.qoder/~/.claude\uFF09" }
1753
+ ],
1754
+ initialValue: "project"
1755
+ });
1756
+ if (prompts2.isCancel(scopeAns)) {
1757
+ throw new Error("Cancelled by user.");
1758
+ }
1759
+ return { ides: idesAns, scope: scopeAns };
1760
+ }
1761
+ function parseIdeList(input) {
1762
+ const parts = input.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
1763
+ const result = [];
1764
+ for (const p of parts) {
1765
+ if (p === "qoder" || p === "claude") {
1766
+ if (!result.includes(p)) result.push(p);
1767
+ } else {
1768
+ throw new Error(`Unknown IDE: "${p}". Expected qoder | claude.`);
1769
+ }
1770
+ }
1771
+ return result;
1772
+ }
1773
+ function parseScope(input) {
1774
+ const v = (input ?? "project").toLowerCase();
1775
+ if (v === "project" || v === "global") return v;
1776
+ throw new Error(`Invalid --scope: "${input}". Expected project | global.`);
1777
+ }
1778
+
1779
+ // src/commands/skills/add.ts
1780
+ import { Command as Command8 } from "commander";
1781
+ import * as prompts3 from "@clack/prompts";
1782
+ var addCommand = new Command8("add").description(
1783
+ "\u589E\u91CF\u6DFB\u52A0 teamix-evo skills\uFF08\u5FC5\u987B\u6307\u5B9A\u81F3\u5C11\u4E00\u4E2A skill id\uFF1B\u81EA\u4E3E\u8BF7\u7528 `skills init`\uFF09"
1784
+ ).argument("<names...>", "\u81F3\u5C11\u4E00\u4E2A skill id\uFF08\u589E\u91CF\u88C5\uFF09").option("--ide <list>", '\u9017\u53F7\u5206\u9694\u7684 IDE \u5217\u8868\uFF0C\u5982 "qoder,claude"').option(
1602
1785
  "--scope <scope>",
1603
- "project | global\uFF08\u9ED8\u8BA4 project\uFF1B\u589E\u91CF\u6A21\u5F0F\u4E0B\u9ED8\u8BA4\u590D\u7528\u5DF2\u6709\u914D\u7F6E\uFF09"
1786
+ "project | global\uFF08\u9ED8\u8BA4\u6CBF\u7528\u65E2\u6709 skills \u914D\u7F6E\uFF1B\u9996\u6B21\u5B89\u88C5\u9ED8\u8BA4 project\uFF09"
1604
1787
  ).option("-y, --yes", "\u4F7F\u7528\u9ED8\u8BA4\u503C\uFF0C\u8DF3\u8FC7\u4EA4\u4E92").action(async (names, opts) => {
1605
1788
  try {
1606
1789
  const ide = detectIde();
1607
1790
  const cwd = ide.getProjectRoot();
1608
- const isIncremental = names.length > 0;
1609
- const { ides, scope } = await resolveIdesAndScope({
1791
+ const { ides, scope } = await resolveIdesAndScope2({
1610
1792
  opts,
1611
- projectRoot: cwd,
1612
- isIncremental
1793
+ projectRoot: cwd
1613
1794
  });
1614
1795
  let projectRoot = cwd;
1615
1796
  if (scope === "global" && !isTeamixEvoProject(cwd)) {
@@ -1622,9 +1803,9 @@ var addCommand = new Command7("add").description(
1622
1803
  process.exit(1);
1623
1804
  }
1624
1805
  logger.info(
1625
- isIncremental ? `Adding skills [${names.join(",")}]: ides=[${ides.join(
1806
+ `Adding skills [${names.join(",")}]: ides=[${ides.join(
1626
1807
  ","
1627
- )}], scope="${scope}"` : `Adding skills (all): ides=[${ides.join(",")}], scope="${scope}"`
1808
+ )}], scope="${scope}"`
1628
1809
  );
1629
1810
  logger.debug(`Project root: ${projectRoot}`);
1630
1811
  const result = await runSkillsAdd({
@@ -1632,14 +1813,8 @@ var addCommand = new Command7("add").description(
1632
1813
  ides,
1633
1814
  scope,
1634
1815
  ide: ide.name,
1635
- names: isIncremental ? names : void 0
1816
+ names
1636
1817
  });
1637
- if (result.status === "already-added") {
1638
- logger.warn(
1639
- `Skills already added. Use "teamix-evo skills add <name>" to add specific skills, "teamix-evo skills update" to refresh, or "teamix-evo skills uninstall" to remove.`
1640
- );
1641
- return;
1642
- }
1643
1818
  if (result.addedSkillIds.length === 0 && result.skippedSkillIds.length > 0) {
1644
1819
  logger.warn(
1645
1820
  `\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u6DFB\u52A0\uFF1A${result.skippedSkillIds.join(
@@ -1668,9 +1843,9 @@ var addCommand = new Command7("add").description(
1668
1843
  process.exitCode = 1;
1669
1844
  }
1670
1845
  });
1671
- async function resolveIdesAndScope(args) {
1672
- const { opts, projectRoot, isIncremental } = args;
1673
- if (isIncremental && !opts.ide && !opts.scope && !opts.yes) {
1846
+ async function resolveIdesAndScope2(args) {
1847
+ const { opts, projectRoot } = args;
1848
+ if (!opts.ide && !opts.scope && !opts.yes) {
1674
1849
  const existing = await readProjectConfig(projectRoot);
1675
1850
  const cfg = existing?.packages?.skills;
1676
1851
  if (cfg && cfg.ides && cfg.ides.length > 0 && cfg.scope) {
@@ -1684,14 +1859,14 @@ async function resolveIdesAndScope(args) {
1684
1859
  }
1685
1860
  }
1686
1861
  if (opts.ide || opts.yes) {
1687
- const ides = opts.ide ? parseIdeList(opts.ide) : [...ALL_IDE_KINDS];
1688
- const scope = parseScope(opts.scope);
1862
+ const ides = opts.ide ? parseIdeList2(opts.ide) : [...ALL_IDE_KINDS];
1863
+ const scope = parseScope2(opts.scope);
1689
1864
  if (ides.length === 0) {
1690
1865
  throw new Error("At least one IDE must be selected.");
1691
1866
  }
1692
1867
  return { ides, scope };
1693
1868
  }
1694
- const idesAns = await prompts2.multiselect({
1869
+ const idesAns = await prompts3.multiselect({
1695
1870
  message: "\u9009\u62E9\u8981\u6CE8\u5165\u6280\u80FD\u7684 AI IDE\uFF08\u81F3\u5C11\u4E00\u4E2A\uFF09",
1696
1871
  options: ALL_IDE_KINDS.map((k) => ({
1697
1872
  value: k,
@@ -1700,10 +1875,10 @@ async function resolveIdesAndScope(args) {
1700
1875
  initialValues: [...ALL_IDE_KINDS],
1701
1876
  required: true
1702
1877
  });
1703
- if (prompts2.isCancel(idesAns)) {
1878
+ if (prompts3.isCancel(idesAns)) {
1704
1879
  throw new Error("Cancelled by user.");
1705
1880
  }
1706
- const scopeAns = await prompts2.select({
1881
+ const scopeAns = await prompts3.select({
1707
1882
  message: "\u5B89\u88C5\u8303\u56F4\uFF1F",
1708
1883
  options: [
1709
1884
  { value: "project", label: "\u9879\u76EE\u7EA7\uFF08.qoder/.claude \u5728\u5F53\u524D\u9879\u76EE\uFF09" },
@@ -1711,12 +1886,12 @@ async function resolveIdesAndScope(args) {
1711
1886
  ],
1712
1887
  initialValue: "project"
1713
1888
  });
1714
- if (prompts2.isCancel(scopeAns)) {
1889
+ if (prompts3.isCancel(scopeAns)) {
1715
1890
  throw new Error("Cancelled by user.");
1716
1891
  }
1717
1892
  return { ides: idesAns, scope: scopeAns };
1718
1893
  }
1719
- function parseIdeList(input) {
1894
+ function parseIdeList2(input) {
1720
1895
  const parts = input.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
1721
1896
  const result = [];
1722
1897
  for (const p of parts) {
@@ -1728,16 +1903,16 @@ function parseIdeList(input) {
1728
1903
  }
1729
1904
  return result;
1730
1905
  }
1731
- function parseScope(input) {
1906
+ function parseScope2(input) {
1732
1907
  const v = (input ?? "project").toLowerCase();
1733
1908
  if (v === "project" || v === "global") return v;
1734
1909
  throw new Error(`Invalid --scope: "${input}". Expected project | global.`);
1735
1910
  }
1736
1911
 
1737
1912
  // src/commands/skills/list.ts
1738
- import { Command as Command8 } from "commander";
1913
+ import { Command as Command9 } from "commander";
1739
1914
  var SKILLS_PACKAGE = "@teamix-evo/skills";
1740
- var listCommand2 = new Command8("list").alias("ls").description(
1915
+ var listCommand2 = new Command9("list").alias("ls").description(
1741
1916
  "\u5217\u51FA teamix-evo skills\uFF08\u9ED8\u8BA4\u5C55\u793A\u5168\u90E8 skill \u5E76\u6807\u6CE8\u5DF2\u88C5/\u672A\u88C5\uFF1B--installed \u4EC5\u770B\u5DF2\u88C5\uFF09"
1742
1917
  ).option("--installed", "\u4EC5\u5C55\u793A\u5DF2\u5B89\u88C5\u7684 skill\uFF08\u9690\u85CF\u672A\u5B89\u88C5\u9879\uFF09").action(async (opts) => {
1743
1918
  try {
@@ -1766,7 +1941,7 @@ var listCommand2 = new Command8("list").alias("ls").description(
1766
1941
  if (opts.installed) {
1767
1942
  if (!config?.packages?.skills || !pkg) {
1768
1943
  logger.info("No skills installed.");
1769
- logger.info('Run "teamix-evo skills add" to get started.');
1944
+ logger.info('Run "teamix-evo skills init" to get started.');
1770
1945
  return;
1771
1946
  }
1772
1947
  printInstalledHeader(config.packages.skills, pkg.installedAt);
@@ -1795,7 +1970,7 @@ var listCommand2 = new Command8("list").alias("ls").description(
1795
1970
  } else {
1796
1971
  logger.info("Skills package not yet added.");
1797
1972
  logger.info(
1798
- 'Run "teamix-evo skills add" to add all, or "teamix-evo skills add <id>" for specific skills.'
1973
+ 'Run "teamix-evo skills init" to bootstrap, or "teamix-evo skills add <id...>" for specific skills.'
1799
1974
  );
1800
1975
  }
1801
1976
  logger.info("");
@@ -1831,10 +2006,185 @@ function printInstalledHeader(cfg, installedAt) {
1831
2006
  }
1832
2007
 
1833
2008
  // src/commands/skills/update.ts
1834
- import { Command as Command9 } from "commander";
1835
- var SKILLS_PACKAGE2 = "@teamix-evo/skills";
2009
+ import { Command as Command10 } from "commander";
2010
+ import { createRequire as createRequire4 } from "module";
2011
+
2012
+ // src/core/skills-update.ts
2013
+ var DEFAULT_SKILLS_PACKAGE3 = "@teamix-evo/skills";
1836
2014
  var FLAT_VARIANT2 = "_flat";
1837
- var updateCommand2 = new Command9("update").description("\u66F4\u65B0\u5DF2\u5B89\u88C5\u7684 teamix-evo skills").action(async () => {
2015
+ async function runSkillsUpdate(options) {
2016
+ const { projectRoot, names: requestedNames, dryRun } = options;
2017
+ const packageName = options.packageName ?? DEFAULT_SKILLS_PACKAGE3;
2018
+ const config = await readProjectConfig(projectRoot);
2019
+ const skillsCfg = config?.packages?.skills;
2020
+ if (!skillsCfg) {
2021
+ return { status: "no-skills" };
2022
+ }
2023
+ const ides = skillsCfg.ides ?? ["qoder", "claude"];
2024
+ const scope = skillsCfg.scope ?? "project";
2025
+ const existingLock = await readSkillsLock(projectRoot);
2026
+ if (!existingLock || Object.keys(existingLock.skills).length === 0) {
2027
+ return { status: "no-skills" };
2028
+ }
2029
+ const { manifest, data, packageRoot } = await loadSkillsData(packageName);
2030
+ const manifestById = new Map(manifest.skills.map((s) => [s.id, s]));
2031
+ const lockIds = Object.keys(existingLock.skills);
2032
+ const requestedSet = requestedNames ? new Set(requestedNames) : null;
2033
+ if (requestedSet) {
2034
+ const unknown = requestedNames.filter(
2035
+ (n) => !lockIds.includes(n) && !manifestById.has(n)
2036
+ );
2037
+ if (unknown.length > 0) {
2038
+ throw new Error(
2039
+ `Unknown skill id(s): ${unknown.join(
2040
+ ", "
2041
+ )}. Available (installed): ${lockIds.join(", ") || "(none)"}.`
2042
+ );
2043
+ }
2044
+ }
2045
+ const targetIds = [];
2046
+ const skippedSkillIds = [];
2047
+ for (const id of lockIds) {
2048
+ if (requestedSet && !requestedSet.has(id)) continue;
2049
+ const entry2 = manifestById.get(id);
2050
+ if (!entry2) {
2051
+ logger.debug(
2052
+ `Skipping "${id}": no longer in upstream manifest. Use \`skills uninstall ${id}\` to remove.`
2053
+ );
2054
+ skippedSkillIds.push(id);
2055
+ continue;
2056
+ }
2057
+ const effectiveScope = entry2.scope ?? "project";
2058
+ if (effectiveScope !== scope) {
2059
+ logger.debug(
2060
+ `Skipping "${id}" (scope=${effectiveScope}): current install scope is "${scope}".`
2061
+ );
2062
+ skippedSkillIds.push(id);
2063
+ continue;
2064
+ }
2065
+ targetIds.push(id);
2066
+ }
2067
+ const allSame = targetIds.every((id) => {
2068
+ const lockVer = existingLock.skills[id].version;
2069
+ const manVer = manifestById.get(id).version;
2070
+ return lockVer === manVer;
2071
+ });
2072
+ if (targetIds.length > 0 && allSame && !dryRun) {
2073
+ return {
2074
+ status: "no-changes",
2075
+ packageName,
2076
+ version: manifest.version,
2077
+ checkedSkillIds: targetIds
2078
+ };
2079
+ }
2080
+ if (dryRun) {
2081
+ const plan = targetIds.map((id) => {
2082
+ const lockVer = existingLock.skills[id].version;
2083
+ const entry2 = manifestById.get(id);
2084
+ const sameVersion = lockVer === entry2.version;
2085
+ return {
2086
+ id,
2087
+ current: lockVer,
2088
+ next: entry2.version,
2089
+ strategy: entry2.updateStrategy ?? "managed",
2090
+ action: sameVersion ? "up-to-date" : "version-bump"
2091
+ };
2092
+ });
2093
+ return {
2094
+ status: "dry-run",
2095
+ packageName,
2096
+ currentVersion: skillsCfg.version,
2097
+ availableVersion: manifest.version,
2098
+ plan
2099
+ };
2100
+ }
2101
+ if (targetIds.length === 0) {
2102
+ return {
2103
+ status: "updated",
2104
+ packageName,
2105
+ version: manifest.version,
2106
+ ides,
2107
+ scope,
2108
+ updatedSkillIds: [],
2109
+ skippedSkillIds,
2110
+ summary: { overwritten: 0, managed: 0, skipped: 0, created: 0 },
2111
+ resources: []
2112
+ };
2113
+ }
2114
+ const result = await updateSkills({
2115
+ projectRoot,
2116
+ manifest,
2117
+ data,
2118
+ packageRoot,
2119
+ ides,
2120
+ scope,
2121
+ onlyIds: targetIds
2122
+ });
2123
+ config.packages.skills = {
2124
+ ...skillsCfg,
2125
+ version: manifest.version
2126
+ };
2127
+ await writeProjectConfig(projectRoot, config);
2128
+ const installedManifest = await readInstalledManifest(projectRoot) ?? {
2129
+ schemaVersion: 1,
2130
+ installed: []
2131
+ };
2132
+ const idx = installedManifest.installed.findIndex(
2133
+ (p) => p.package === packageName
2134
+ );
2135
+ const installedAt = (/* @__PURE__ */ new Date()).toISOString();
2136
+ const prior = idx >= 0 ? installedManifest.installed[idx].resources : [];
2137
+ const targetSet = new Set(targetIds);
2138
+ const preserved = prior.filter((r) => {
2139
+ const skillId = r.id.split(":")[0];
2140
+ return skillId ? !targetSet.has(skillId) : true;
2141
+ });
2142
+ const entry = {
2143
+ package: packageName,
2144
+ variant: FLAT_VARIANT2,
2145
+ version: manifest.version,
2146
+ installedAt,
2147
+ resources: [...preserved, ...result.resources]
2148
+ };
2149
+ if (idx >= 0) installedManifest.installed[idx] = entry;
2150
+ else installedManifest.installed.push(entry);
2151
+ await writeInstalledManifest(projectRoot, installedManifest);
2152
+ const lock = {
2153
+ schemaVersion: 1,
2154
+ skills: { ...existingLock.skills }
2155
+ };
2156
+ for (const id of targetIds) {
2157
+ const skillDef = manifestById.get(id);
2158
+ if (!skillDef) continue;
2159
+ const mirroredTo = skillDef.ides.filter((i) => ides.includes(i));
2160
+ lock.skills[id] = {
2161
+ version: skillDef.version,
2162
+ from: packageName,
2163
+ installedAt,
2164
+ scope,
2165
+ mirroredTo
2166
+ };
2167
+ }
2168
+ await writeSkillsLock(projectRoot, lock);
2169
+ return {
2170
+ status: "updated",
2171
+ packageName,
2172
+ version: manifest.version,
2173
+ ides,
2174
+ scope,
2175
+ updatedSkillIds: targetIds,
2176
+ skippedSkillIds,
2177
+ summary: result.summary,
2178
+ resources: result.resources
2179
+ };
2180
+ }
2181
+
2182
+ // src/commands/skills/update.ts
2183
+ var require5 = createRequire4(import.meta.url);
2184
+ var SKILLS_PACKAGE2 = "@teamix-evo/skills";
2185
+ var updateCommand2 = new Command10("update").description(
2186
+ "\u66F4\u65B0\u5DF2\u5B89\u88C5\u7684 teamix-evo skills\uFF08\u4EC5\u5347\u7EA7 lock \u5DF2\u8BB0\u5F55\u4E14 scope \u5339\u914D\u7684 skill \u2014 ADR 0035\uFF09"
2187
+ ).argument("[names...]", "\u53EF\u9009\uFF1A\u4EC5\u5347\u7EA7\u6307\u5B9A skill id;\u7701\u7565\u5219\u5347\u7EA7\u5168\u90E8\u5DF2\u88C5").option("--dry-run", "\u9884\u89C8\u53D8\u66F4\uFF0C\u4E0D\u5199\u76D8").action(async (names, opts) => {
1838
2188
  try {
1839
2189
  const ide = detectIde();
1840
2190
  const cwd = ide.getProjectRoot();
@@ -1842,95 +2192,101 @@ var updateCommand2 = new Command9("update").description("\u66F4\u65B0\u5DF2\u5B8
1842
2192
  if (projectRoot !== cwd) {
1843
2193
  logger.info(`Using global skills meta root: ${projectRoot}`);
1844
2194
  }
1845
- const config = await readProjectConfig(projectRoot);
1846
- if (!config?.packages?.skills) {
1847
- logger.error('Skills not added. Run "teamix-evo skills add" first.');
1848
- process.exitCode = 1;
1849
- return;
1850
- }
1851
- const installedManifest = await readInstalledManifest(projectRoot);
1852
- if (!installedManifest) {
1853
- logger.error("No installed manifest found.");
1854
- process.exitCode = 1;
1855
- return;
1856
- }
1857
- const skillsEntry = config.packages.skills;
1858
- const ides = skillsEntry.ides ?? [
1859
- "qoder",
1860
- "claude"
1861
- ];
1862
- const scope = skillsEntry.scope ?? "project";
1863
- logger.info(`Updating skills (ides=[${ides.join(",")}], scope=${scope})`);
1864
- const { manifest, data, packageRoot } = await loadSkillsData(
1865
- SKILLS_PACKAGE2
1866
- );
1867
- logger.info(
1868
- `Current: v${skillsEntry.version} \u2192 Available: v${manifest.version}`
1869
- );
1870
- const result = await updateSkills({
2195
+ await printVersionBanner();
2196
+ const result = await runSkillsUpdate({
1871
2197
  projectRoot,
1872
- manifest,
1873
- data,
1874
- packageRoot,
1875
- ides,
1876
- scope
2198
+ names: names.length > 0 ? names : void 0,
2199
+ dryRun: opts.dryRun
1877
2200
  });
1878
- config.packages.skills.version = manifest.version;
1879
- await writeProjectConfig(projectRoot, config);
1880
- const installedAt = (/* @__PURE__ */ new Date()).toISOString();
1881
- const idx = installedManifest.installed.findIndex(
1882
- (p) => p.package === SKILLS_PACKAGE2
1883
- );
1884
- const entry = {
1885
- package: SKILLS_PACKAGE2,
1886
- variant: FLAT_VARIANT2,
1887
- version: manifest.version,
1888
- installedAt,
1889
- resources: result.resources
1890
- };
1891
- if (idx >= 0) installedManifest.installed[idx] = entry;
1892
- else installedManifest.installed.push(entry);
1893
- await writeInstalledManifest(projectRoot, installedManifest);
1894
- const existingLock = await readSkillsLock(projectRoot) ?? {
1895
- schemaVersion: 1,
1896
- skills: {}
1897
- };
1898
- const lock = {
1899
- schemaVersion: 1,
1900
- skills: { ...existingLock.skills }
1901
- };
1902
- for (const skill of manifest.skills) {
1903
- const mirroredTo = skill.ides.filter((i) => ides.includes(i));
1904
- if (mirroredTo.length === 0) continue;
1905
- lock.skills[skill.id] = {
1906
- version: skill.version,
1907
- from: SKILLS_PACKAGE2,
1908
- installedAt,
1909
- scope,
1910
- mirroredTo
1911
- };
2201
+ switch (result.status) {
2202
+ case "no-skills":
2203
+ logger.error(
2204
+ 'Skills not added. Run "teamix-evo skills init" first.'
2205
+ );
2206
+ process.exitCode = 1;
2207
+ return;
2208
+ case "no-changes":
2209
+ logger.success(
2210
+ `Already up-to-date (skills package v${result.version}).`
2211
+ );
2212
+ logger.info(
2213
+ ` Checked: ${result.checkedSkillIds.join(", ") || "(none)"}`
2214
+ );
2215
+ return;
2216
+ case "dry-run":
2217
+ logger.info(
2218
+ `Plan (${result.currentVersion} \u2192 ${result.availableVersion}):`
2219
+ );
2220
+ if (result.plan.length === 0) {
2221
+ logger.info(" (no skills to update)");
2222
+ } else {
2223
+ for (const item of result.plan) {
2224
+ logger.info(formatPlanItem(item));
2225
+ }
2226
+ }
2227
+ logger.info("");
2228
+ logger.info("Re-run without --dry-run to apply.");
2229
+ return;
2230
+ case "updated": {
2231
+ const { summary } = result;
2232
+ logger.success(
2233
+ `Skills updated to v${result.version} (${result.updatedSkillIds.length} skill(s)).`
2234
+ );
2235
+ if (result.updatedSkillIds.length > 0) {
2236
+ logger.info(
2237
+ ` Updated: ${result.updatedSkillIds.join(", ")}`
2238
+ );
2239
+ }
2240
+ if (result.skippedSkillIds.length > 0) {
2241
+ logger.info(
2242
+ ` Skipped: ${result.skippedSkillIds.join(", ")} (scope mismatch / removed upstream)`
2243
+ );
2244
+ }
2245
+ logger.info(` Created: ${summary.created}`);
2246
+ logger.info(` Overwritten: ${summary.overwritten}`);
2247
+ logger.info(` Managed: ${summary.managed}`);
2248
+ logger.info(` Skipped: ${summary.skipped}`);
2249
+ return;
2250
+ }
1912
2251
  }
1913
- await writeSkillsLock(projectRoot, lock);
1914
- const { summary } = result;
1915
- logger.success(`Skills updated to v${manifest.version}`);
1916
- logger.info(` Created: ${summary.created}`);
1917
- logger.info(` Overwritten: ${summary.overwritten}`);
1918
- logger.info(` Managed: ${summary.managed}`);
1919
- logger.info(` Skipped: ${summary.skipped}`);
1920
2252
  } catch (err) {
1921
2253
  logger.error(`Failed to update skills: ${err.message}`);
1922
2254
  logger.debug(err.stack ?? "");
1923
2255
  process.exitCode = 1;
1924
2256
  }
1925
2257
  });
2258
+ function formatPlanItem(item) {
2259
+ const tag = item.action === "up-to-date" ? " =" : item.strategy === "frozen" ? " \u2298 " : item.strategy === "managed" ? " \u2295 " : " \u2192 ";
2260
+ const ver = item.action === "up-to-date" ? `v${item.current} (no change)` : `v${item.current} \u2192 v${item.next} [${item.strategy}]`;
2261
+ return `${tag}${item.id} ${ver}`;
2262
+ }
2263
+ async function printVersionBanner() {
2264
+ let cliVersion;
2265
+ try {
2266
+ const pkg = require5("../package.json");
2267
+ cliVersion = pkg.version;
2268
+ } catch {
2269
+ }
2270
+ try {
2271
+ const { manifest } = await loadSkillsData(SKILLS_PACKAGE2);
2272
+ if (cliVersion) {
2273
+ logger.info(
2274
+ `teamix-evo CLI v${cliVersion} \xB7 skills package v${manifest.version}`
2275
+ );
2276
+ } else {
2277
+ logger.info(`skills package v${manifest.version}`);
2278
+ }
2279
+ } catch {
2280
+ }
2281
+ }
1926
2282
 
1927
2283
  // src/commands/skills/uninstall.ts
1928
- import { Command as Command10 } from "commander";
1929
- import * as prompts3 from "@clack/prompts";
2284
+ import { Command as Command11 } from "commander";
2285
+ import * as prompts4 from "@clack/prompts";
1930
2286
  import * as path13 from "path";
1931
2287
  import * as fs10 from "fs/promises";
1932
2288
  var SKILLS_PACKAGE3 = "@teamix-evo/skills";
1933
- var uninstallCommand2 = new Command10("uninstall").description(
2289
+ var uninstallCommand2 = new Command11("uninstall").description(
1934
2290
  "\u5378\u8F7D\u5DF2\u5B89\u88C5\u7684 teamix-evo skills\uFF1B\u4E0D\u4F20 ids \u5219\u5378\u8F7D\u6574\u5305\uFF0C\u4F20 ids \u5219\u6309 skill \u5220\u9664"
1935
2291
  ).argument(
1936
2292
  "[ids...]",
@@ -1984,11 +2340,11 @@ async function runFullUninstall(args) {
1984
2340
  `Will remove ${resources.length} skill file(s) installed by ${SKILLS_PACKAGE3}.`
1985
2341
  );
1986
2342
  if (!opts.yes) {
1987
- const confirm4 = await prompts3.confirm({
2343
+ const confirm5 = await prompts4.confirm({
1988
2344
  message: "\u786E\u8BA4\u5378\u8F7D\uFF1F\u6B64\u64CD\u4F5C\u4F1A\u5220\u9664\u4E0A\u8FF0\u6587\u4EF6\u3002",
1989
2345
  initialValue: false
1990
2346
  });
1991
- if (prompts3.isCancel(confirm4) || !confirm4) {
2347
+ if (prompts4.isCancel(confirm5) || !confirm5) {
1992
2348
  logger.info("Cancelled.");
1993
2349
  return;
1994
2350
  }
@@ -2053,11 +2409,11 @@ async function runPartialUninstall(args) {
2053
2409
  `Will remove ${matched.length} skill(s): ${matched.join(", ")} (${toRemove.length} file(s)).`
2054
2410
  );
2055
2411
  if (!opts.yes) {
2056
- const confirm4 = await prompts3.confirm({
2412
+ const confirm5 = await prompts4.confirm({
2057
2413
  message: "\u786E\u8BA4\u5378\u8F7D\uFF1F\u6B64\u64CD\u4F5C\u4F1A\u5220\u9664\u4E0A\u8FF0\u6587\u4EF6\u3002",
2058
2414
  initialValue: false
2059
2415
  });
2060
- if (prompts3.isCancel(confirm4) || !confirm4) {
2416
+ if (prompts4.isCancel(confirm5) || !confirm5) {
2061
2417
  logger.info("Cancelled.");
2062
2418
  return;
2063
2419
  }
@@ -2174,17 +2530,17 @@ function dedupe(values) {
2174
2530
  }
2175
2531
 
2176
2532
  // src/commands/skills/sync.ts
2177
- import { Command as Command11 } from "commander";
2533
+ import { Command as Command12 } from "commander";
2178
2534
 
2179
2535
  // src/core/skills-sync.ts
2180
2536
  import * as path14 from "path";
2181
2537
  import * as fs11 from "fs/promises";
2182
- import { createRequire as createRequire4 } from "module";
2538
+ import { createRequire as createRequire5 } from "module";
2183
2539
  import { loadSkillsPackageManifest as loadSkillsPackageManifest2 } from "@teamix-evo/registry";
2184
- var require5 = createRequire4(import.meta.url);
2540
+ var require6 = createRequire5(import.meta.url);
2185
2541
  async function readSkillMetaFromUpstream(skillId) {
2186
2542
  try {
2187
- const pkgJson = require5.resolve("@teamix-evo/skills/package.json");
2543
+ const pkgJson = require6.resolve("@teamix-evo/skills/package.json");
2188
2544
  const packageRoot = path14.dirname(pkgJson);
2189
2545
  const manifest = await loadSkillsPackageManifest2(packageRoot);
2190
2546
  const entry = manifest.skills.find((s) => s.id === skillId);
@@ -2283,7 +2639,7 @@ async function refreshMirrorRecords(projectRoot, newMirrorRecords) {
2283
2639
  }
2284
2640
 
2285
2641
  // src/commands/skills/sync.ts
2286
- var syncCommand = new Command11("sync").description(
2642
+ var syncCommand = new Command12("sync").description(
2287
2643
  "\u628A .teamix-evo/skills/ \u4E0B\u7684\u6E90\u91CD\u65B0\u955C\u50CF\u5230 IDE \u8DEF\u5F84\uFF08.qoder / .claude\uFF09"
2288
2644
  ).argument(
2289
2645
  "[names...]",
@@ -2302,8 +2658,8 @@ var syncCommand = new Command11("sync").description(
2302
2658
  if (projectRoot !== cwd) {
2303
2659
  logger.info(`Using global skills meta root: ${projectRoot}`);
2304
2660
  }
2305
- const ides = opts.ide ? parseIdeList2(opts.ide) : void 0;
2306
- const scope = opts.scope ? parseScope2(opts.scope) : void 0;
2661
+ const ides = opts.ide ? parseIdeList3(opts.ide) : void 0;
2662
+ const scope = opts.scope ? parseScope3(opts.scope) : void 0;
2307
2663
  const result = await runSkillsSync({
2308
2664
  projectRoot,
2309
2665
  ides,
@@ -2335,7 +2691,7 @@ var syncCommand = new Command11("sync").description(
2335
2691
  process.exitCode = 1;
2336
2692
  }
2337
2693
  });
2338
- function parseIdeList2(input) {
2694
+ function parseIdeList3(input) {
2339
2695
  const parts = input.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
2340
2696
  const result = [];
2341
2697
  for (const p of parts) {
@@ -2349,14 +2705,14 @@ function parseIdeList2(input) {
2349
2705
  }
2350
2706
  return result;
2351
2707
  }
2352
- function parseScope2(input) {
2708
+ function parseScope3(input) {
2353
2709
  const v = input.toLowerCase();
2354
2710
  if (v === "project" || v === "global") return v;
2355
2711
  throw new Error(`Invalid --scope: "${input}". Expected project | global.`);
2356
2712
  }
2357
2713
 
2358
2714
  // src/commands/skills/doctor.ts
2359
- import { Command as Command12 } from "commander";
2715
+ import { Command as Command13 } from "commander";
2360
2716
 
2361
2717
  // src/core/skills-doctor.ts
2362
2718
  import * as path15 from "path";
@@ -2375,7 +2731,7 @@ async function runSkillsDoctor(options) {
2375
2731
  kind: "missing-source",
2376
2732
  skillId,
2377
2733
  path: sourceDir,
2378
- detail: 'Run "teamix-evo skills add" to reinstall.'
2734
+ detail: 'Run "teamix-evo skills init" to reinstall.'
2379
2735
  });
2380
2736
  continue;
2381
2737
  }
@@ -2445,7 +2801,7 @@ async function dirExists2(p) {
2445
2801
  }
2446
2802
 
2447
2803
  // src/commands/skills/doctor.ts
2448
- var doctorCommand = new Command12("doctor").description(
2804
+ var doctorCommand = new Command13("doctor").description(
2449
2805
  "\u68C0\u67E5 .teamix-evo/skills/ \u6E90\u4E0E IDE \u955C\u50CF\u662F\u5426\u6F02\u79FB\uFF1B\u63D0\u793A\u5982\u4F55\u4FEE\u590D"
2450
2806
  ).action(async () => {
2451
2807
  try {
@@ -2458,7 +2814,7 @@ var doctorCommand = new Command12("doctor").description(
2458
2814
  const result = await runSkillsDoctor({ projectRoot });
2459
2815
  if (result.status === "no-skills") {
2460
2816
  logger.info(
2461
- 'No skills recorded. Run "teamix-evo skills add" first.'
2817
+ 'No skills recorded. Run "teamix-evo skills init" first.'
2462
2818
  );
2463
2819
  return;
2464
2820
  }
@@ -2484,9 +2840,10 @@ var doctorCommand = new Command12("doctor").description(
2484
2840
  });
2485
2841
 
2486
2842
  // src/commands/skills/index.ts
2487
- var skillsCommand = new Command13("skills").description(
2843
+ var skillsCommand = new Command14("skills").description(
2488
2844
  "\u7BA1\u7406 teamix-evo skills\uFF08\u5411 AI IDE \u6CE8\u5165\u6280\u80FD\uFF1Bsource-mirror \u6A21\u578B\u89C1 ADR 0013\uFF09"
2489
2845
  );
2846
+ skillsCommand.addCommand(initCommand2);
2490
2847
  skillsCommand.addCommand(addCommand);
2491
2848
  skillsCommand.addCommand(listCommand2);
2492
2849
  skillsCommand.addCommand(updateCommand2);
@@ -2495,11 +2852,11 @@ skillsCommand.addCommand(doctorCommand);
2495
2852
  skillsCommand.addCommand(uninstallCommand2);
2496
2853
 
2497
2854
  // src/commands/ui/index.ts
2498
- import { Command as Command17 } from "commander";
2855
+ import { Command as Command18 } from "commander";
2499
2856
 
2500
2857
  // src/commands/ui/init.ts
2501
- import { Command as Command14 } from "commander";
2502
- import * as prompts4 from "@clack/prompts";
2858
+ import { Command as Command15 } from "commander";
2859
+ import * as prompts5 from "@clack/prompts";
2503
2860
 
2504
2861
  // src/core/ui-init.ts
2505
2862
  var DEFAULT_UI_ALIASES = {
@@ -2556,7 +2913,7 @@ async function runUiInit(options) {
2556
2913
  }
2557
2914
 
2558
2915
  // src/commands/ui/init.ts
2559
- var initCommand2 = new Command14("init").description(
2916
+ var initCommand3 = new Command15("init").description(
2560
2917
  "\u521D\u59CB\u5316 teamix-evo ui \u914D\u7F6E\uFF08\u8BE2\u95EE aliases / iconLibrary / tsx / rsc\uFF09"
2561
2918
  ).option("-y, --yes", "\u4F7F\u7528\u9ED8\u8BA4\u503C\uFF0C\u8DF3\u8FC7\u4EA4\u4E92").option(
2562
2919
  "--components <path>",
@@ -2603,7 +2960,8 @@ var initCommand2 = new Command14("init").description(
2603
2960
  }
2604
2961
  });
2605
2962
  async function resolveConfig(opts) {
2606
- if (opts.yes) {
2963
+ const isInteractive = Boolean(process.stdin.isTTY);
2964
+ if (opts.yes || !isInteractive) {
2607
2965
  return {
2608
2966
  aliases: {
2609
2967
  components: opts.components ?? DEFAULT_UI_ALIASES.components,
@@ -2618,41 +2976,41 @@ async function resolveConfig(opts) {
2618
2976
  rsc: opts.rsc ?? false
2619
2977
  };
2620
2978
  }
2621
- const components = await prompts4.text({
2979
+ const components = await prompts5.text({
2622
2980
  message: "components \u8DEF\u5F84\uFF08\u6CE8\u5165\u6309\u94AE\u7B49\u7EC4\u4EF6\u6E90\u7801\u7684\u76EE\u5F55\uFF09",
2623
2981
  initialValue: opts.components ?? DEFAULT_UI_ALIASES.components
2624
2982
  });
2625
- if (prompts4.isCancel(components)) throw new Error("Cancelled by user.");
2626
- const hooks = await prompts4.text({
2983
+ if (prompts5.isCancel(components)) throw new Error("Cancelled by user.");
2984
+ const hooks = await prompts5.text({
2627
2985
  message: "hooks \u8DEF\u5F84",
2628
2986
  initialValue: opts.hooks ?? DEFAULT_UI_ALIASES.hooks
2629
2987
  });
2630
- if (prompts4.isCancel(hooks)) throw new Error("Cancelled by user.");
2631
- const utils = await prompts4.text({
2988
+ if (prompts5.isCancel(hooks)) throw new Error("Cancelled by user.");
2989
+ const utils = await prompts5.text({
2632
2990
  message: "utils \u8DEF\u5F84\uFF08cn \u7B49\u5DE5\u5177\uFF09",
2633
2991
  initialValue: opts.utils ?? DEFAULT_UI_ALIASES.utils
2634
2992
  });
2635
- if (prompts4.isCancel(utils)) throw new Error("Cancelled by user.");
2636
- const lib = await prompts4.text({
2993
+ if (prompts5.isCancel(utils)) throw new Error("Cancelled by user.");
2994
+ const lib = await prompts5.text({
2637
2995
  message: "lib \u8DEF\u5F84\uFF08\u5171\u4EAB\u4EE3\u7801\u6839\uFF09",
2638
2996
  initialValue: opts.lib ?? DEFAULT_UI_ALIASES.lib
2639
2997
  });
2640
- if (prompts4.isCancel(lib)) throw new Error("Cancelled by user.");
2641
- const iconLibrary = await prompts4.text({
2998
+ if (prompts5.isCancel(lib)) throw new Error("Cancelled by user.");
2999
+ const iconLibrary = await prompts5.text({
2642
3000
  message: "icon \u5E93\uFF08\u58F0\u660E\u6027\uFF0C\u7EC4\u4EF6\u6E90\u7801\u5DF2 hardcode lucide-react\uFF09",
2643
3001
  initialValue: opts.iconLibrary ?? "lucide"
2644
3002
  });
2645
- if (prompts4.isCancel(iconLibrary)) throw new Error("Cancelled by user.");
2646
- const tsxAns = await prompts4.confirm({
3003
+ if (prompts5.isCancel(iconLibrary)) throw new Error("Cancelled by user.");
3004
+ const tsxAns = await prompts5.confirm({
2647
3005
  message: "\u4F7F\u7528 TSX\uFF1F",
2648
3006
  initialValue: opts.tsx ?? true
2649
3007
  });
2650
- if (prompts4.isCancel(tsxAns)) throw new Error("Cancelled by user.");
2651
- const rscAns = await prompts4.confirm({
3008
+ if (prompts5.isCancel(tsxAns)) throw new Error("Cancelled by user.");
3009
+ const rscAns = await prompts5.confirm({
2652
3010
  message: "\u4F7F\u7528 React Server Components\uFF1F",
2653
3011
  initialValue: opts.rsc ?? false
2654
3012
  });
2655
- if (prompts4.isCancel(rscAns)) throw new Error("Cancelled by user.");
3013
+ if (prompts5.isCancel(rscAns)) throw new Error("Cancelled by user.");
2656
3014
  return {
2657
3015
  aliases: {
2658
3016
  components,
@@ -2669,16 +3027,16 @@ async function resolveConfig(opts) {
2669
3027
  }
2670
3028
 
2671
3029
  // src/commands/ui/add.ts
2672
- import { Command as Command15 } from "commander";
3030
+ import { Command as Command16 } from "commander";
2673
3031
 
2674
3032
  // src/core/ui-client.ts
2675
3033
  import * as path16 from "path";
2676
3034
  import * as fs13 from "fs/promises";
2677
- import { createRequire as createRequire5 } from "module";
3035
+ import { createRequire as createRequire6 } from "module";
2678
3036
  import { loadUiPackageManifest } from "@teamix-evo/registry";
2679
- var require6 = createRequire5(import.meta.url);
3037
+ var require7 = createRequire6(import.meta.url);
2680
3038
  function resolvePackageRoot2(packageName) {
2681
- const pkgJsonPath = require6.resolve(`${packageName}/package.json`);
3039
+ const pkgJsonPath = require7.resolve(`${packageName}/package.json`);
2682
3040
  return path16.dirname(pkgJsonPath);
2683
3041
  }
2684
3042
  async function loadUiData(packageName) {
@@ -2894,7 +3252,7 @@ function mergeResources(prior, next) {
2894
3252
  }
2895
3253
 
2896
3254
  // src/commands/ui/add.ts
2897
- var addCommand2 = new Command15("add").description(
3255
+ var addCommand2 = new Command16("add").description(
2898
3256
  "\u5B89\u88C5\u4E00\u4E2A\u6216\u591A\u4E2A ui entry\uFF08\u6309 id\uFF0C\u81EA\u52A8\u5C55\u5F00 registryDependencies\uFF09"
2899
3257
  ).argument("<ids...>", 'entry id \u5217\u8868\uFF0C\u5982 "button" "dialog"').option("--overwrite", "\u5373\u4F7F\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\u5728\u4E5F\u8986\u76D6\uFF08\u7ED5\u8FC7 frozen \u8DF3\u8FC7\uFF09").option(
2900
3258
  "--include-deprecated",
@@ -2940,7 +3298,7 @@ var addCommand2 = new Command15("add").description(
2940
3298
  );
2941
3299
 
2942
3300
  // src/commands/ui/list.ts
2943
- import { Command as Command16 } from "commander";
3301
+ import { Command as Command17 } from "commander";
2944
3302
 
2945
3303
  // src/core/ui-list.ts
2946
3304
  var DEFAULT_UI_PACKAGE2 = "@teamix-evo/ui";
@@ -2978,7 +3336,7 @@ async function runUiList(options) {
2978
3336
  }
2979
3337
 
2980
3338
  // src/commands/ui/list.ts
2981
- var listCommand3 = new Command16("list").description("\u5217\u51FA @teamix-evo/ui \u7684\u6240\u6709 entry \u53CA\u5DF2\u5B89\u88C5\u72B6\u6001").option("--installed", "\u4EC5\u5C55\u793A\u5DF2\u5B89\u88C5\u7684 entry").option(
3339
+ var listCommand3 = new Command17("list").description("\u5217\u51FA @teamix-evo/ui \u7684\u6240\u6709 entry \u53CA\u5DF2\u5B89\u88C5\u72B6\u6001").option("--installed", "\u4EC5\u5C55\u793A\u5DF2\u5B89\u88C5\u7684 entry").option(
2982
3340
  "--include-deprecated",
2983
3341
  "\u540C\u65F6\u5217\u51FA\u5DF2\u5F52\u6863\u7684 deprecated entry\uFF08\u9ED8\u8BA4\u9690\u85CF\uFF0CADR 0028\uFF09"
2984
3342
  ).action(
@@ -3030,30 +3388,30 @@ var listCommand3 = new Command16("list").description("\u5217\u51FA @teamix-evo/u
3030
3388
  );
3031
3389
 
3032
3390
  // src/commands/ui/index.ts
3033
- var uiCommand = new Command17("ui").description(
3391
+ var uiCommand = new Command18("ui").description(
3034
3392
  "\u7BA1\u7406 teamix-evo ui \u7EC4\u4EF6\uFF08\u6E90\u7801\u6CE8\u5165\u5F0F\u5B89\u88C5\uFF0Cshadcn \u98CE\u683C\uFF09"
3035
3393
  );
3036
- uiCommand.addCommand(initCommand2);
3394
+ uiCommand.addCommand(initCommand3);
3037
3395
  uiCommand.addCommand(addCommand2);
3038
3396
  uiCommand.addCommand(listCommand3);
3039
3397
 
3040
3398
  // src/commands/biz-ui/index.ts
3041
- import { Command as Command21 } from "commander";
3399
+ import { Command as Command22 } from "commander";
3042
3400
 
3043
3401
  // src/commands/biz-ui/add.ts
3044
- import { Command as Command18 } from "commander";
3402
+ import { Command as Command19 } from "commander";
3045
3403
 
3046
3404
  // src/core/variant-ui-add.ts
3047
3405
  import * as path18 from "path";
3048
- import { createRequire as createRequire6 } from "module";
3406
+ import { createRequire as createRequire7 } from "module";
3049
3407
  import {
3050
3408
  loadUiPackageManifest as loadUiPackageManifest2,
3051
3409
  loadVariantUiPackageCatalog,
3052
3410
  loadVariantUiPackageManifest
3053
3411
  } from "@teamix-evo/registry";
3054
- var require7 = createRequire6(import.meta.url);
3412
+ var require8 = createRequire7(import.meta.url);
3055
3413
  function resolvePackageRoot3(packageName) {
3056
- const pkgJsonPath = require7.resolve(`${packageName}/package.json`);
3414
+ const pkgJsonPath = require8.resolve(`${packageName}/package.json`);
3057
3415
  return path18.dirname(pkgJsonPath);
3058
3416
  }
3059
3417
  async function runVariantUiAdd(packageName, options) {
@@ -3212,7 +3570,7 @@ async function listTemplatesEntries(variant, packageRoot) {
3212
3570
  }
3213
3571
 
3214
3572
  // src/commands/biz-ui/add.ts
3215
- var addCommand3 = new Command18("add").description(
3573
+ var addCommand3 = new Command19("add").description(
3216
3574
  "\u5B89\u88C5\u4E00\u4E2A\u6216\u591A\u4E2A\u4E1A\u52A1 UI \u7EC4\u4EF6(\u6309 id,\u81EA\u52A8\u5C55\u5F00 ui \u5305\u7684 registryDependencies)"
3217
3575
  ).argument("<ids...>", '\u7EC4\u4EF6 id \u5217\u8868,\u5982 "tenant-switcher" "org-picker"').option("--variant <name>", '\u53D8\u4F53 id(\u5FC5\u586B,\u5982 "opentrek"\u3001"uni-manager")').option("--overwrite", "\u5373\u4F7F\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\u5728\u4E5F\u8986\u76D6").action(
3218
3576
  async (ids, opts) => {
@@ -3261,8 +3619,8 @@ var addCommand3 = new Command18("add").description(
3261
3619
  );
3262
3620
 
3263
3621
  // src/commands/biz-ui/list.ts
3264
- import { Command as Command19 } from "commander";
3265
- var listCommand4 = new Command19("list").description("\u5217\u51FA\u6307\u5B9A\u53D8\u4F53\u4E0B\u7684 biz-ui entries").requiredOption("--variant <name>", "\u53D8\u4F53\u540D\uFF08\u5982 opentrek / uni-manager\uFF09").action(async (opts) => {
3622
+ import { Command as Command20 } from "commander";
3623
+ var listCommand4 = new Command20("list").description("\u5217\u51FA\u6307\u5B9A\u53D8\u4F53\u4E0B\u7684 biz-ui entries").requiredOption("--variant <name>", "\u53D8\u4F53\u540D\uFF08\u5982 opentrek / uni-manager\uFF09").action(async (opts) => {
3266
3624
  try {
3267
3625
  const result = await listBizUiEntries(opts.variant);
3268
3626
  logger.info(`${result.packageName}#${result.variant} entries:`);
@@ -3287,8 +3645,8 @@ var listCommand4 = new Command19("list").description("\u5217\u51FA\u6307\u5B9A\u
3287
3645
  });
3288
3646
 
3289
3647
  // src/commands/biz-ui/list-variants.ts
3290
- import { Command as Command20 } from "commander";
3291
- var listVariantsCommand2 = new Command20("list-variants").description("\u5217\u51FA @teamix-evo/biz-ui \u5305\u5185\u63D0\u4F9B\u7684\u6240\u6709\u4E1A\u52A1\u53D8\u4F53").action(async () => {
3648
+ import { Command as Command21 } from "commander";
3649
+ var listVariantsCommand2 = new Command21("list-variants").description("\u5217\u51FA @teamix-evo/biz-ui \u5305\u5185\u63D0\u4F9B\u7684\u6240\u6709\u4E1A\u52A1\u53D8\u4F53").action(async () => {
3292
3650
  try {
3293
3651
  const result = await listBizUiVariants();
3294
3652
  logger.info(`Available biz-ui variants in ${result.packageName}:`);
@@ -3310,7 +3668,7 @@ var listVariantsCommand2 = new Command20("list-variants").description("\u5217\u5
3310
3668
  });
3311
3669
 
3312
3670
  // src/commands/biz-ui/index.ts
3313
- var bizUiCommand = new Command21("biz-ui").description(
3671
+ var bizUiCommand = new Command22("biz-ui").description(
3314
3672
  "\u7BA1\u7406\u4E1A\u52A1 UI \u7EC4\u4EF6(\u53D8\u4F53\u611F\u77E5 \u2014 \u4E0E design / templates \u540C\u53D8\u4F53\u540D\u7A7A\u95F4)"
3315
3673
  );
3316
3674
  bizUiCommand.addCommand(addCommand3);
@@ -3318,11 +3676,11 @@ bizUiCommand.addCommand(listCommand4);
3318
3676
  bizUiCommand.addCommand(listVariantsCommand2);
3319
3677
 
3320
3678
  // src/commands/templates/index.ts
3321
- import { Command as Command25 } from "commander";
3679
+ import { Command as Command26 } from "commander";
3322
3680
 
3323
3681
  // src/commands/templates/add.ts
3324
- import { Command as Command22 } from "commander";
3325
- var addCommand4 = new Command22("add").description(
3682
+ import { Command as Command23 } from "commander";
3683
+ var addCommand4 = new Command23("add").description(
3326
3684
  "\u5B89\u88C5\u4E00\u4E2A\u6216\u591A\u4E2A\u9875\u9762\u6A21\u677F(\u6309 id,\u81EA\u52A8\u5C55\u5F00 ui \u5305\u7684 registryDependencies)"
3327
3685
  ).argument("<ids...>", '\u6A21\u677F id \u5217\u8868,\u5982 "list-detail-page"').option("--variant <name>", '\u53D8\u4F53 id(\u5FC5\u586B,\u5982 "opentrek"\u3001"uni-manager")').option("--overwrite", "\u5373\u4F7F\u76EE\u6807\u6587\u4EF6\u5DF2\u5B58\u5728\u4E5F\u8986\u76D6").action(
3328
3686
  async (ids, opts) => {
@@ -3371,8 +3729,8 @@ var addCommand4 = new Command22("add").description(
3371
3729
  );
3372
3730
 
3373
3731
  // src/commands/templates/list.ts
3374
- import { Command as Command23 } from "commander";
3375
- var listCommand5 = new Command23("list").description("\u5217\u51FA\u6307\u5B9A\u53D8\u4F53\u4E0B\u7684 templates entries").requiredOption("--variant <name>", "\u53D8\u4F53\u540D\uFF08\u5982 opentrek / uni-manager\uFF09").action(async (opts) => {
3732
+ import { Command as Command24 } from "commander";
3733
+ var listCommand5 = new Command24("list").description("\u5217\u51FA\u6307\u5B9A\u53D8\u4F53\u4E0B\u7684 templates entries").requiredOption("--variant <name>", "\u53D8\u4F53\u540D\uFF08\u5982 opentrek / uni-manager\uFF09").action(async (opts) => {
3376
3734
  try {
3377
3735
  const result = await listTemplatesEntries(opts.variant);
3378
3736
  logger.info(`${result.packageName}#${result.variant} entries:`);
@@ -3397,8 +3755,8 @@ var listCommand5 = new Command23("list").description("\u5217\u51FA\u6307\u5B9A\u
3397
3755
  });
3398
3756
 
3399
3757
  // src/commands/templates/list-variants.ts
3400
- import { Command as Command24 } from "commander";
3401
- var listVariantsCommand3 = new Command24("list-variants").description("\u5217\u51FA @teamix-evo/templates \u5305\u5185\u63D0\u4F9B\u7684\u6240\u6709\u9875\u9762\u6A21\u677F\u53D8\u4F53").action(async () => {
3758
+ import { Command as Command25 } from "commander";
3759
+ var listVariantsCommand3 = new Command25("list-variants").description("\u5217\u51FA @teamix-evo/templates \u5305\u5185\u63D0\u4F9B\u7684\u6240\u6709\u9875\u9762\u6A21\u677F\u53D8\u4F53").action(async () => {
3402
3760
  try {
3403
3761
  const result = await listTemplatesVariants();
3404
3762
  logger.info(`Available templates variants in ${result.packageName}:`);
@@ -3420,7 +3778,7 @@ var listVariantsCommand3 = new Command24("list-variants").description("\u5217\u5
3420
3778
  });
3421
3779
 
3422
3780
  // src/commands/templates/index.ts
3423
- var templatesCommand = new Command25("templates").description(
3781
+ var templatesCommand = new Command26("templates").description(
3424
3782
  "\u7BA1\u7406\u9875\u9762\u6A21\u677F(\u53D8\u4F53\u611F\u77E5 \u2014 \u4E0E design / biz-ui \u540C\u53D8\u4F53\u540D\u7A7A\u95F4)"
3425
3783
  );
3426
3784
  templatesCommand.addCommand(addCommand4);
@@ -3428,24 +3786,26 @@ templatesCommand.addCommand(listCommand5);
3428
3786
  templatesCommand.addCommand(listVariantsCommand3);
3429
3787
 
3430
3788
  // src/commands/logs/index.ts
3431
- import { Command as Command28 } from "commander";
3789
+ import { Command as Command29 } from "commander";
3432
3790
 
3433
3791
  // src/commands/logs/analyze.ts
3434
- import { Command as Command26 } from "commander";
3792
+ import { Command as Command27 } from "commander";
3435
3793
  import { readFileSync, readdirSync, existsSync as existsSync2, statSync } from "fs";
3436
3794
  import { resolve as resolve3, join as join17 } from "path";
3437
3795
  var DATE_DIR_RE = /^\d{4}-\d{2}-\d{2}$/;
3438
- var logsAnalyzeCommand = new Command26("analyze").description(
3439
- "\u6C47\u603B vibe-logger \u8F93\u51FA (.log/ai/**/*.jsonl) \u2014 \u5DE5\u5177 / \u5305\u6807\u7B7E / MCP \u8C03\u7528\u9891\u7387,\u8F85\u52A9\u751F\u6001\u4F18\u5316"
3440
- ).option("--dir <path>", "log \u76EE\u5F55 (\u9ED8\u8BA4 <project>/.log/ai)").option(
3796
+ var logsAnalyzeCommand = new Command27("analyze").description(
3797
+ "\u6C47\u603B vibe-logger \u8F93\u51FA (.teamix-evo/logs/ai/**/*.jsonl) \u2014 \u5DE5\u5177 / \u5305\u6807\u7B7E / MCP \u8C03\u7528\u9891\u7387,\u8F85\u52A9\u751F\u6001\u4F18\u5316"
3798
+ ).option("--dir <path>", "log \u76EE\u5F55 (\u9ED8\u8BA4 <project>/.teamix-evo/logs/ai)").option(
3441
3799
  "--days <n>",
3442
3800
  "\u53EA\u770B\u6700\u8FD1 N \u5929\u7684\u76EE\u5F55 (\u9ED8\u8BA4\u5168\u90E8;\u6309\u76EE\u5F55\u540D YYYY-MM-DD \u6BD4\u5BF9,\u4E0D\u89E3\u6790\u8BB0\u5F55 ts)"
3443
3801
  ).option("--top <n>", "\u6BCF\u4E2A\u6392\u884C\u5C55\u793A\u524D N \u9879 (\u9ED8\u8BA4 10)", "10").option("--json", "\u4EE5 JSON \u8F93\u51FA (CI/\u5DE5\u5177\u53CB\u597D)").action((opts) => {
3444
- const baseDir = resolve3(opts.dir ?? join17(process.cwd(), ".log", "ai"));
3802
+ const baseDir = resolve3(
3803
+ opts.dir ?? join17(process.cwd(), ".teamix-evo", "logs", "ai")
3804
+ );
3445
3805
  if (!existsSync2(baseDir)) {
3446
3806
  logger.warn(`No log directory at ${baseDir}.`);
3447
3807
  logger.info(
3448
- "\u8FD0\u884C vibe-logger hook \u89E6\u53D1\u540E\u4F1A\u5728\u6B64\u76EE\u5F55\u751F\u6210 JSONL \u2014 \u89C1 .claude/scripts/vibe-logger.mjs"
3808
+ "\u8FD0\u884C vibe-logger hook \u89E6\u53D1\u540E\u4F1A\u5728\u6B64\u76EE\u5F55\u751F\u6210 JSONL \u2014 \u89C1 .claude/scripts/vibe-logger.mjs\uFF08\u9ED8\u8BA4\u8DEF\u5F84 .teamix-evo/logs/ai\uFF09"
3449
3809
  );
3450
3810
  return;
3451
3811
  }
@@ -3615,18 +3975,20 @@ function parseIntOrUndef(v) {
3615
3975
  }
3616
3976
 
3617
3977
  // src/commands/logs/trace.ts
3618
- import { Command as Command27 } from "commander";
3978
+ import { Command as Command28 } from "commander";
3619
3979
  import { readFileSync as readFileSync2, readdirSync as readdirSync2, existsSync as existsSync3, statSync as statSync2 } from "fs";
3620
3980
  import { resolve as resolve4, join as join18 } from "path";
3621
3981
  var DATE_DIR_RE2 = /^\d{4}-\d{2}-\d{2}$/;
3622
- var logsTraceCommand = new Command27("trace").description(
3982
+ var logsTraceCommand = new Command28("trace").description(
3623
3983
  "\u6309\u4F1A\u8BDD\u8FD8\u539F AI \u8C03\u7528\u94FE\u8DEF:\u4ECE\u7528\u6237 prompt \u8D77\u59CB,\u4E32\u8054\u540E\u7EED PreToolUse/PostToolUse \u76F4\u5230\u4E0B\u4E00\u4E2A prompt \u6216 Stop"
3624
- ).option("--prompt <keyword>", "\u6309\u7528\u6237\u8F93\u5165\u5173\u952E\u5B57\u8FC7\u6EE4 (\u5B50\u4E32\u5339\u914D,\u4E0D\u533A\u5206\u5927\u5C0F\u5199)").option("--session <id>", "\u6307\u5B9A\u4F1A\u8BDD ID (\u524D\u7F00\u5339\u914D)").option("--days <n>", "\u53EA\u770B\u6700\u8FD1 N \u5929\u7684\u76EE\u5F55 (\u9ED8\u8BA4 7)", "7").option("--dir <path>", "log \u76EE\u5F55 (\u9ED8\u8BA4 <project>/.log/ai)").option("--json", "\u4EE5 JSON \u8F93\u51FA (CI/\u5DE5\u5177\u53CB\u597D)").action((opts) => {
3625
- const baseDir = resolve4(opts.dir ?? join18(process.cwd(), ".log", "ai"));
3984
+ ).option("--prompt <keyword>", "\u6309\u7528\u6237\u8F93\u5165\u5173\u952E\u5B57\u8FC7\u6EE4 (\u5B50\u4E32\u5339\u914D,\u4E0D\u533A\u5206\u5927\u5C0F\u5199)").option("--session <id>", "\u6307\u5B9A\u4F1A\u8BDD ID (\u524D\u7F00\u5339\u914D)").option("--days <n>", "\u53EA\u770B\u6700\u8FD1 N \u5929\u7684\u76EE\u5F55 (\u9ED8\u8BA4 7)", "7").option("--dir <path>", "log \u76EE\u5F55 (\u9ED8\u8BA4 <project>/.teamix-evo/logs/ai)").option("--json", "\u4EE5 JSON \u8F93\u51FA (CI/\u5DE5\u5177\u53CB\u597D)").action((opts) => {
3985
+ const baseDir = resolve4(
3986
+ opts.dir ?? join18(process.cwd(), ".teamix-evo", "logs", "ai")
3987
+ );
3626
3988
  if (!existsSync3(baseDir)) {
3627
3989
  logger.warn(`No log directory at ${baseDir}.`);
3628
3990
  logger.info(
3629
- "\u8FD0\u884C vibe-logger hook \u89E6\u53D1\u540E\u4F1A\u5728\u6B64\u76EE\u5F55\u751F\u6210 JSONL \u2014 \u89C1 .claude/scripts/vibe-logger.mjs"
3991
+ "\u8FD0\u884C vibe-logger hook \u89E6\u53D1\u540E\u4F1A\u5728\u6B64\u76EE\u5F55\u751F\u6210 JSONL \u2014 \u89C1 .claude/scripts/vibe-logger.mjs\uFF08\u9ED8\u8BA4\u8DEF\u5F84 .teamix-evo/logs/ai\uFF09"
3630
3992
  );
3631
3993
  return;
3632
3994
  }
@@ -3778,7 +4140,9 @@ function printTrace(baseDir, r) {
3778
4140
  logger.info("");
3779
4141
  for (const c of s.chains) {
3780
4142
  logger.info(
3781
- `[${formatTime(c.promptTs)}] \u{1F4AC} Prompt: ${quote(truncate(c.prompt, 200))}`
4143
+ `[${formatTime(c.promptTs)}] \u{1F4AC} Prompt: ${quote(
4144
+ truncate(c.prompt, 200)
4145
+ )}`
3782
4146
  );
3783
4147
  for (const step of c.steps) {
3784
4148
  logger.info(` ${formatStep(step)}`);
@@ -3825,16 +4189,176 @@ function parseIntOrUndef2(v) {
3825
4189
  }
3826
4190
 
3827
4191
  // src/commands/logs/index.ts
3828
- var logsCommand = new Command28("logs").description(
3829
- "\u67E5\u8BE2 vibe-logger \u8F93\u51FA (.log/ai/**/*.jsonl) \u2014 AI \u8C03\u7528\u94FE\u5206\u6790"
4192
+ var logsCommand = new Command29("logs").description(
4193
+ "\u67E5\u8BE2 vibe-logger \u8F93\u51FA (.teamix-evo/logs/ai/**/*.jsonl) \u2014 AI \u8C03\u7528\u94FE\u5206\u6790"
3830
4194
  );
3831
4195
  logsCommand.addCommand(logsAnalyzeCommand);
3832
4196
  logsCommand.addCommand(logsTraceCommand);
3833
4197
 
4198
+ // src/commands/lint/index.ts
4199
+ import { Command as Command31 } from "commander";
4200
+
4201
+ // src/commands/lint/init.ts
4202
+ import { Command as Command30 } from "commander";
4203
+ import * as prompts6 from "@clack/prompts";
4204
+
4205
+ // src/core/lint-init.ts
4206
+ import * as path19 from "path";
4207
+ import * as fs15 from "fs";
4208
+ import { execa } from "execa";
4209
+ var ESLINT_CONFIG_CONTENT = `/**
4210
+ * teamix-evo consumer ESLint preset \u2014 9 token-discipline rules.
4211
+ * - Repo-wide: no-color-literal / no-arbitrary-tw-value / no-raw-color-scale /
4212
+ * no-large-radius / prefer-gap-over-space / no-manual-dark-classnames /
4213
+ * dialog-must-have-title (all error)
4214
+ * - src/components/ui/** only: no-relative-ui-import / icon-from-lucide (error)
4215
+ *
4216
+ * See ADR 0008 / docs/principles.md \xA7P4.
4217
+ */
4218
+ import consumerPreset from '@teamix-evo/eslint-config/presets/consumer';
4219
+
4220
+ export default [...consumerPreset];
4221
+ `;
4222
+ var STYLELINT_CONFIG_CONTENT = `/** @type {import('stylelint').Config} */
4223
+ module.exports = {
4224
+ extends: ['@teamix-evo/stylelint-config/presets/consumer'],
4225
+ };
4226
+ `;
4227
+ var ESLINT_DEPS = [
4228
+ "@teamix-evo/eslint-config",
4229
+ "eslint",
4230
+ "@typescript-eslint/parser"
4231
+ ];
4232
+ var STYLELINT_DEPS = ["@teamix-evo/stylelint-config", "stylelint"];
4233
+ async function runLintInit(options) {
4234
+ const { projectRoot, skipInstall } = options;
4235
+ const eslintConfigPath = path19.join(projectRoot, "eslint.config.js");
4236
+ const stylelintConfigPath = path19.join(projectRoot, "stylelint.config.cjs");
4237
+ const eslintExists = await fileExists(eslintConfigPath);
4238
+ const stylelintExists = await fileExists(stylelintConfigPath);
4239
+ if (eslintExists && stylelintExists) {
4240
+ return { status: "already-initialized" };
4241
+ }
4242
+ if (!skipInstall) {
4243
+ const depsToInstall = [
4244
+ ...eslintExists ? [] : ESLINT_DEPS,
4245
+ ...stylelintExists ? [] : STYLELINT_DEPS
4246
+ ];
4247
+ if (depsToInstall.length > 0) {
4248
+ const pm = detectPm(projectRoot);
4249
+ const args = pm === "yarn" ? ["add", "--dev", ...depsToInstall] : pm === "pnpm" ? ["add", "-D", ...depsToInstall] : ["install", "--save-dev", ...depsToInstall];
4250
+ logger.info(`Installing lint deps via ${pm}...`);
4251
+ await execa(pm, args, { cwd: projectRoot, stdio: "inherit" });
4252
+ }
4253
+ }
4254
+ let wroteEslint = false;
4255
+ let wroteStylelint = false;
4256
+ if (!eslintExists) {
4257
+ await writeFileSafe(eslintConfigPath, ESLINT_CONFIG_CONTENT);
4258
+ logger.debug(`Wrote eslint.config.js \u2192 ${eslintConfigPath}`);
4259
+ wroteEslint = true;
4260
+ }
4261
+ if (!stylelintExists) {
4262
+ await writeFileSafe(stylelintConfigPath, STYLELINT_CONFIG_CONTENT);
4263
+ logger.debug(`Wrote stylelint.config.cjs \u2192 ${stylelintConfigPath}`);
4264
+ wroteStylelint = true;
4265
+ }
4266
+ await patchPackageJsonScripts(projectRoot);
4267
+ return {
4268
+ status: "installed",
4269
+ eslint: wroteEslint,
4270
+ stylelint: wroteStylelint
4271
+ };
4272
+ }
4273
+ function detectPm(projectRoot) {
4274
+ if (fs15.existsSync(path19.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
4275
+ if (fs15.existsSync(path19.join(projectRoot, "yarn.lock"))) return "yarn";
4276
+ return "npm";
4277
+ }
4278
+ async function patchPackageJsonScripts(projectRoot) {
4279
+ const pkgPath = path19.join(projectRoot, "package.json");
4280
+ const raw = await readFileOrNull(pkgPath);
4281
+ if (!raw) return;
4282
+ let pkg;
4283
+ try {
4284
+ pkg = JSON.parse(raw);
4285
+ } catch {
4286
+ return;
4287
+ }
4288
+ const scripts = pkg.scripts ?? {};
4289
+ let changed = false;
4290
+ if (!scripts.lint) {
4291
+ scripts.lint = "eslint src/";
4292
+ changed = true;
4293
+ }
4294
+ if (!scripts["lint:css"]) {
4295
+ scripts["lint:css"] = "stylelint 'src/**/*.css'";
4296
+ changed = true;
4297
+ }
4298
+ if (changed) {
4299
+ pkg.scripts = scripts;
4300
+ await writeFileSafe(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
4301
+ logger.debug("Patched package.json scripts with lint / lint:css");
4302
+ }
4303
+ }
4304
+
4305
+ // src/commands/lint/init.ts
4306
+ var initCommand4 = new Command30("init").description(
4307
+ "\u521D\u59CB\u5316 ESLint + Stylelint \u5DE5\u7A0B\u89C4\u8303\uFF08\u5B89\u88C5\u4F9D\u8D56 + \u751F\u6210\u914D\u7F6E\u6587\u4EF6 + \u6CE8\u5165 scripts\uFF09"
4308
+ ).option("-y, --yes", "\u8DF3\u8FC7\u786E\u8BA4\uFF0C\u76F4\u63A5\u6267\u884C").action(async (opts) => {
4309
+ try {
4310
+ const ide = detectIde();
4311
+ const projectRoot = ide.getProjectRoot();
4312
+ if (!hasPackageJson(projectRoot)) {
4313
+ logger.error(
4314
+ "No package.json found in current directory. Please run this command in a valid project root."
4315
+ );
4316
+ process.exit(1);
4317
+ }
4318
+ const isInteractive = Boolean(process.stdin.isTTY);
4319
+ if (!opts.yes && isInteractive) {
4320
+ const shouldContinue = await prompts6.confirm({
4321
+ message: "\u5373\u5C06\u5B89\u88C5 ESLint + Stylelint token-discipline \u89C4\u5219\u96C6\u5E76\u751F\u6210\u914D\u7F6E\u6587\u4EF6\uFF0C\u662F\u5426\u7EE7\u7EED\uFF1F"
4322
+ });
4323
+ if (prompts6.isCancel(shouldContinue) || !shouldContinue) {
4324
+ logger.info("Cancelled.");
4325
+ return;
4326
+ }
4327
+ }
4328
+ const result = await runLintInit({ projectRoot });
4329
+ if (result.status === "already-initialized") {
4330
+ logger.warn(
4331
+ "Lint already initialized. eslint.config.js and stylelint.config.cjs both exist."
4332
+ );
4333
+ return;
4334
+ }
4335
+ logger.success("Lint initialized.");
4336
+ if (result.eslint) {
4337
+ logger.info(" + eslint.config.js");
4338
+ }
4339
+ if (result.stylelint) {
4340
+ logger.info(" + stylelint.config.cjs");
4341
+ }
4342
+ logger.info("");
4343
+ logger.info('Run "npm run lint" to check JSX/TSX token discipline.');
4344
+ logger.info('Run "npm run lint:css" to check CSS token discipline.');
4345
+ } catch (err) {
4346
+ logger.error(`Failed to initialize lint: ${err.message}`);
4347
+ logger.debug(err.stack ?? "");
4348
+ process.exitCode = 1;
4349
+ }
4350
+ });
4351
+
4352
+ // src/commands/lint/index.ts
4353
+ var lintCommand = new Command31("lint").description(
4354
+ "\u7BA1\u7406\u5DE5\u7A0B\u89C4\u8303\uFF08ESLint + Stylelint token-discipline \u89C4\u5219\u96C6\uFF09"
4355
+ );
4356
+ lintCommand.addCommand(initCommand4);
4357
+
3834
4358
  // src/index.ts
3835
- var require8 = createRequire7(import.meta.url);
3836
- var { version } = require8("../package.json");
3837
- var program = new Command29();
4359
+ var require9 = createRequire8(import.meta.url);
4360
+ var { version } = require9("../package.json");
4361
+ var program = new Command32();
3838
4362
  program.name("teamix-evo").description("Where ideas evolve. \u2014 AI Coding \u5957\u4EF6").version(version);
3839
4363
  program.addCommand(tokensCommand);
3840
4364
  program.addCommand(skillsCommand);
@@ -3842,5 +4366,11 @@ program.addCommand(uiCommand);
3842
4366
  program.addCommand(bizUiCommand);
3843
4367
  program.addCommand(templatesCommand);
3844
4368
  program.addCommand(logsCommand);
4369
+ program.addCommand(lintCommand);
4370
+ function enableHelpAfterError(cmd) {
4371
+ cmd.showHelpAfterError(true);
4372
+ for (const child of cmd.commands) enableHelpAfterError(child);
4373
+ }
4374
+ enableHelpAfterError(program);
3845
4375
  program.parse();
3846
4376
  //# sourceMappingURL=index.js.map