teamix-evo 0.4.1 → 0.6.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
@@ -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,132 @@ 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
+ if (opts.ide || opts.yes) {
1728
+ const ides = opts.ide ? parseIdeList(opts.ide) : [...ALL_IDE_KINDS];
1729
+ const scope = parseScope(opts.scope);
1730
+ if (ides.length === 0) {
1731
+ throw new Error("At least one IDE must be selected.");
1732
+ }
1733
+ return { ides, scope };
1734
+ }
1735
+ const idesAns = await prompts2.multiselect({
1736
+ message: "\u9009\u62E9\u8981\u6CE8\u5165\u6280\u80FD\u7684 AI IDE\uFF08\u81F3\u5C11\u4E00\u4E2A\uFF09",
1737
+ options: ALL_IDE_KINDS.map((k) => ({
1738
+ value: k,
1739
+ label: k === "qoder" ? "Qoder" : "Claude Code"
1740
+ })),
1741
+ initialValues: [...ALL_IDE_KINDS],
1742
+ required: true
1743
+ });
1744
+ if (prompts2.isCancel(idesAns)) {
1745
+ throw new Error("Cancelled by user.");
1746
+ }
1747
+ const scopeAns = await prompts2.select({
1748
+ message: "\u5B89\u88C5\u8303\u56F4\uFF1F",
1749
+ options: [
1750
+ { value: "project", label: "\u9879\u76EE\u7EA7\uFF08.qoder/.claude \u5728\u5F53\u524D\u9879\u76EE\uFF09" },
1751
+ { value: "global", label: "\u5168\u5C40\uFF08~/.qoder/~/.claude\uFF09" }
1752
+ ],
1753
+ initialValue: "project"
1754
+ });
1755
+ if (prompts2.isCancel(scopeAns)) {
1756
+ throw new Error("Cancelled by user.");
1757
+ }
1758
+ return { ides: idesAns, scope: scopeAns };
1759
+ }
1760
+ function parseIdeList(input) {
1761
+ const parts = input.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
1762
+ const result = [];
1763
+ for (const p of parts) {
1764
+ if (p === "qoder" || p === "claude") {
1765
+ if (!result.includes(p)) result.push(p);
1766
+ } else {
1767
+ throw new Error(`Unknown IDE: "${p}". Expected qoder | claude.`);
1768
+ }
1769
+ }
1770
+ return result;
1771
+ }
1772
+ function parseScope(input) {
1773
+ const v = (input ?? "project").toLowerCase();
1774
+ if (v === "project" || v === "global") return v;
1775
+ throw new Error(`Invalid --scope: "${input}". Expected project | global.`);
1776
+ }
1777
+
1778
+ // src/commands/skills/add.ts
1779
+ import { Command as Command8 } from "commander";
1780
+ import * as prompts3 from "@clack/prompts";
1781
+ var addCommand = new Command8("add").description(
1782
+ "\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"
1783
+ ).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
1784
  "--scope <scope>",
1603
- "project | global\uFF08\u9ED8\u8BA4 project\uFF1B\u589E\u91CF\u6A21\u5F0F\u4E0B\u9ED8\u8BA4\u590D\u7528\u5DF2\u6709\u914D\u7F6E\uFF09"
1785
+ "project | global\uFF08\u9ED8\u8BA4\u6CBF\u7528\u65E2\u6709 skills \u914D\u7F6E\uFF1B\u9996\u6B21\u5B89\u88C5\u9ED8\u8BA4 project\uFF09"
1604
1786
  ).option("-y, --yes", "\u4F7F\u7528\u9ED8\u8BA4\u503C\uFF0C\u8DF3\u8FC7\u4EA4\u4E92").action(async (names, opts) => {
1605
1787
  try {
1606
1788
  const ide = detectIde();
1607
1789
  const cwd = ide.getProjectRoot();
1608
- const isIncremental = names.length > 0;
1609
- const { ides, scope } = await resolveIdesAndScope({
1790
+ const { ides, scope } = await resolveIdesAndScope2({
1610
1791
  opts,
1611
- projectRoot: cwd,
1612
- isIncremental
1792
+ projectRoot: cwd
1613
1793
  });
1614
1794
  let projectRoot = cwd;
1615
1795
  if (scope === "global" && !isTeamixEvoProject(cwd)) {
@@ -1622,9 +1802,9 @@ var addCommand = new Command7("add").description(
1622
1802
  process.exit(1);
1623
1803
  }
1624
1804
  logger.info(
1625
- isIncremental ? `Adding skills [${names.join(",")}]: ides=[${ides.join(
1805
+ `Adding skills [${names.join(",")}]: ides=[${ides.join(
1626
1806
  ","
1627
- )}], scope="${scope}"` : `Adding skills (all): ides=[${ides.join(",")}], scope="${scope}"`
1807
+ )}], scope="${scope}"`
1628
1808
  );
1629
1809
  logger.debug(`Project root: ${projectRoot}`);
1630
1810
  const result = await runSkillsAdd({
@@ -1632,14 +1812,8 @@ var addCommand = new Command7("add").description(
1632
1812
  ides,
1633
1813
  scope,
1634
1814
  ide: ide.name,
1635
- names: isIncremental ? names : void 0
1815
+ names
1636
1816
  });
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
1817
  if (result.addedSkillIds.length === 0 && result.skippedSkillIds.length > 0) {
1644
1818
  logger.warn(
1645
1819
  `\u5DF2\u5B58\u5728\uFF0C\u65E0\u9700\u6DFB\u52A0\uFF1A${result.skippedSkillIds.join(
@@ -1668,9 +1842,9 @@ var addCommand = new Command7("add").description(
1668
1842
  process.exitCode = 1;
1669
1843
  }
1670
1844
  });
1671
- async function resolveIdesAndScope(args) {
1672
- const { opts, projectRoot, isIncremental } = args;
1673
- if (isIncremental && !opts.ide && !opts.scope && !opts.yes) {
1845
+ async function resolveIdesAndScope2(args) {
1846
+ const { opts, projectRoot } = args;
1847
+ if (!opts.ide && !opts.scope && !opts.yes) {
1674
1848
  const existing = await readProjectConfig(projectRoot);
1675
1849
  const cfg = existing?.packages?.skills;
1676
1850
  if (cfg && cfg.ides && cfg.ides.length > 0 && cfg.scope) {
@@ -1684,14 +1858,14 @@ async function resolveIdesAndScope(args) {
1684
1858
  }
1685
1859
  }
1686
1860
  if (opts.ide || opts.yes) {
1687
- const ides = opts.ide ? parseIdeList(opts.ide) : [...ALL_IDE_KINDS];
1688
- const scope = parseScope(opts.scope);
1861
+ const ides = opts.ide ? parseIdeList2(opts.ide) : [...ALL_IDE_KINDS];
1862
+ const scope = parseScope2(opts.scope);
1689
1863
  if (ides.length === 0) {
1690
1864
  throw new Error("At least one IDE must be selected.");
1691
1865
  }
1692
1866
  return { ides, scope };
1693
1867
  }
1694
- const idesAns = await prompts2.multiselect({
1868
+ const idesAns = await prompts3.multiselect({
1695
1869
  message: "\u9009\u62E9\u8981\u6CE8\u5165\u6280\u80FD\u7684 AI IDE\uFF08\u81F3\u5C11\u4E00\u4E2A\uFF09",
1696
1870
  options: ALL_IDE_KINDS.map((k) => ({
1697
1871
  value: k,
@@ -1700,10 +1874,10 @@ async function resolveIdesAndScope(args) {
1700
1874
  initialValues: [...ALL_IDE_KINDS],
1701
1875
  required: true
1702
1876
  });
1703
- if (prompts2.isCancel(idesAns)) {
1877
+ if (prompts3.isCancel(idesAns)) {
1704
1878
  throw new Error("Cancelled by user.");
1705
1879
  }
1706
- const scopeAns = await prompts2.select({
1880
+ const scopeAns = await prompts3.select({
1707
1881
  message: "\u5B89\u88C5\u8303\u56F4\uFF1F",
1708
1882
  options: [
1709
1883
  { value: "project", label: "\u9879\u76EE\u7EA7\uFF08.qoder/.claude \u5728\u5F53\u524D\u9879\u76EE\uFF09" },
@@ -1711,12 +1885,12 @@ async function resolveIdesAndScope(args) {
1711
1885
  ],
1712
1886
  initialValue: "project"
1713
1887
  });
1714
- if (prompts2.isCancel(scopeAns)) {
1888
+ if (prompts3.isCancel(scopeAns)) {
1715
1889
  throw new Error("Cancelled by user.");
1716
1890
  }
1717
1891
  return { ides: idesAns, scope: scopeAns };
1718
1892
  }
1719
- function parseIdeList(input) {
1893
+ function parseIdeList2(input) {
1720
1894
  const parts = input.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
1721
1895
  const result = [];
1722
1896
  for (const p of parts) {
@@ -1728,16 +1902,16 @@ function parseIdeList(input) {
1728
1902
  }
1729
1903
  return result;
1730
1904
  }
1731
- function parseScope(input) {
1905
+ function parseScope2(input) {
1732
1906
  const v = (input ?? "project").toLowerCase();
1733
1907
  if (v === "project" || v === "global") return v;
1734
1908
  throw new Error(`Invalid --scope: "${input}". Expected project | global.`);
1735
1909
  }
1736
1910
 
1737
1911
  // src/commands/skills/list.ts
1738
- import { Command as Command8 } from "commander";
1912
+ import { Command as Command9 } from "commander";
1739
1913
  var SKILLS_PACKAGE = "@teamix-evo/skills";
1740
- var listCommand2 = new Command8("list").alias("ls").description(
1914
+ var listCommand2 = new Command9("list").alias("ls").description(
1741
1915
  "\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
1916
  ).option("--installed", "\u4EC5\u5C55\u793A\u5DF2\u5B89\u88C5\u7684 skill\uFF08\u9690\u85CF\u672A\u5B89\u88C5\u9879\uFF09").action(async (opts) => {
1743
1917
  try {
@@ -1766,7 +1940,7 @@ var listCommand2 = new Command8("list").alias("ls").description(
1766
1940
  if (opts.installed) {
1767
1941
  if (!config?.packages?.skills || !pkg) {
1768
1942
  logger.info("No skills installed.");
1769
- logger.info('Run "teamix-evo skills add" to get started.');
1943
+ logger.info('Run "teamix-evo skills init" to get started.');
1770
1944
  return;
1771
1945
  }
1772
1946
  printInstalledHeader(config.packages.skills, pkg.installedAt);
@@ -1795,7 +1969,7 @@ var listCommand2 = new Command8("list").alias("ls").description(
1795
1969
  } else {
1796
1970
  logger.info("Skills package not yet added.");
1797
1971
  logger.info(
1798
- 'Run "teamix-evo skills add" to add all, or "teamix-evo skills add <id>" for specific skills.'
1972
+ 'Run "teamix-evo skills init" to bootstrap, or "teamix-evo skills add <id...>" for specific skills.'
1799
1973
  );
1800
1974
  }
1801
1975
  logger.info("");
@@ -1831,10 +2005,185 @@ function printInstalledHeader(cfg, installedAt) {
1831
2005
  }
1832
2006
 
1833
2007
  // src/commands/skills/update.ts
1834
- import { Command as Command9 } from "commander";
1835
- var SKILLS_PACKAGE2 = "@teamix-evo/skills";
2008
+ import { Command as Command10 } from "commander";
2009
+ import { createRequire as createRequire4 } from "module";
2010
+
2011
+ // src/core/skills-update.ts
2012
+ var DEFAULT_SKILLS_PACKAGE3 = "@teamix-evo/skills";
1836
2013
  var FLAT_VARIANT2 = "_flat";
1837
- var updateCommand2 = new Command9("update").description("\u66F4\u65B0\u5DF2\u5B89\u88C5\u7684 teamix-evo skills").action(async () => {
2014
+ async function runSkillsUpdate(options) {
2015
+ const { projectRoot, names: requestedNames, dryRun } = options;
2016
+ const packageName = options.packageName ?? DEFAULT_SKILLS_PACKAGE3;
2017
+ const config = await readProjectConfig(projectRoot);
2018
+ const skillsCfg = config?.packages?.skills;
2019
+ if (!skillsCfg) {
2020
+ return { status: "no-skills" };
2021
+ }
2022
+ const ides = skillsCfg.ides ?? ["qoder", "claude"];
2023
+ const scope = skillsCfg.scope ?? "project";
2024
+ const existingLock = await readSkillsLock(projectRoot);
2025
+ if (!existingLock || Object.keys(existingLock.skills).length === 0) {
2026
+ return { status: "no-skills" };
2027
+ }
2028
+ const { manifest, data, packageRoot } = await loadSkillsData(packageName);
2029
+ const manifestById = new Map(manifest.skills.map((s) => [s.id, s]));
2030
+ const lockIds = Object.keys(existingLock.skills);
2031
+ const requestedSet = requestedNames ? new Set(requestedNames) : null;
2032
+ if (requestedSet) {
2033
+ const unknown = requestedNames.filter(
2034
+ (n) => !lockIds.includes(n) && !manifestById.has(n)
2035
+ );
2036
+ if (unknown.length > 0) {
2037
+ throw new Error(
2038
+ `Unknown skill id(s): ${unknown.join(
2039
+ ", "
2040
+ )}. Available (installed): ${lockIds.join(", ") || "(none)"}.`
2041
+ );
2042
+ }
2043
+ }
2044
+ const targetIds = [];
2045
+ const skippedSkillIds = [];
2046
+ for (const id of lockIds) {
2047
+ if (requestedSet && !requestedSet.has(id)) continue;
2048
+ const entry2 = manifestById.get(id);
2049
+ if (!entry2) {
2050
+ logger.debug(
2051
+ `Skipping "${id}": no longer in upstream manifest. Use \`skills uninstall ${id}\` to remove.`
2052
+ );
2053
+ skippedSkillIds.push(id);
2054
+ continue;
2055
+ }
2056
+ const effectiveScope = entry2.scope ?? "project";
2057
+ if (effectiveScope !== scope) {
2058
+ logger.debug(
2059
+ `Skipping "${id}" (scope=${effectiveScope}): current install scope is "${scope}".`
2060
+ );
2061
+ skippedSkillIds.push(id);
2062
+ continue;
2063
+ }
2064
+ targetIds.push(id);
2065
+ }
2066
+ const allSame = targetIds.every((id) => {
2067
+ const lockVer = existingLock.skills[id].version;
2068
+ const manVer = manifestById.get(id).version;
2069
+ return lockVer === manVer;
2070
+ });
2071
+ if (targetIds.length > 0 && allSame && !dryRun) {
2072
+ return {
2073
+ status: "no-changes",
2074
+ packageName,
2075
+ version: manifest.version,
2076
+ checkedSkillIds: targetIds
2077
+ };
2078
+ }
2079
+ if (dryRun) {
2080
+ const plan = targetIds.map((id) => {
2081
+ const lockVer = existingLock.skills[id].version;
2082
+ const entry2 = manifestById.get(id);
2083
+ const sameVersion = lockVer === entry2.version;
2084
+ return {
2085
+ id,
2086
+ current: lockVer,
2087
+ next: entry2.version,
2088
+ strategy: entry2.updateStrategy ?? "managed",
2089
+ action: sameVersion ? "up-to-date" : "version-bump"
2090
+ };
2091
+ });
2092
+ return {
2093
+ status: "dry-run",
2094
+ packageName,
2095
+ currentVersion: skillsCfg.version,
2096
+ availableVersion: manifest.version,
2097
+ plan
2098
+ };
2099
+ }
2100
+ if (targetIds.length === 0) {
2101
+ return {
2102
+ status: "updated",
2103
+ packageName,
2104
+ version: manifest.version,
2105
+ ides,
2106
+ scope,
2107
+ updatedSkillIds: [],
2108
+ skippedSkillIds,
2109
+ summary: { overwritten: 0, managed: 0, skipped: 0, created: 0 },
2110
+ resources: []
2111
+ };
2112
+ }
2113
+ const result = await updateSkills({
2114
+ projectRoot,
2115
+ manifest,
2116
+ data,
2117
+ packageRoot,
2118
+ ides,
2119
+ scope,
2120
+ onlyIds: targetIds
2121
+ });
2122
+ config.packages.skills = {
2123
+ ...skillsCfg,
2124
+ version: manifest.version
2125
+ };
2126
+ await writeProjectConfig(projectRoot, config);
2127
+ const installedManifest = await readInstalledManifest(projectRoot) ?? {
2128
+ schemaVersion: 1,
2129
+ installed: []
2130
+ };
2131
+ const idx = installedManifest.installed.findIndex(
2132
+ (p) => p.package === packageName
2133
+ );
2134
+ const installedAt = (/* @__PURE__ */ new Date()).toISOString();
2135
+ const prior = idx >= 0 ? installedManifest.installed[idx].resources : [];
2136
+ const targetSet = new Set(targetIds);
2137
+ const preserved = prior.filter((r) => {
2138
+ const skillId = r.id.split(":")[0];
2139
+ return skillId ? !targetSet.has(skillId) : true;
2140
+ });
2141
+ const entry = {
2142
+ package: packageName,
2143
+ variant: FLAT_VARIANT2,
2144
+ version: manifest.version,
2145
+ installedAt,
2146
+ resources: [...preserved, ...result.resources]
2147
+ };
2148
+ if (idx >= 0) installedManifest.installed[idx] = entry;
2149
+ else installedManifest.installed.push(entry);
2150
+ await writeInstalledManifest(projectRoot, installedManifest);
2151
+ const lock = {
2152
+ schemaVersion: 1,
2153
+ skills: { ...existingLock.skills }
2154
+ };
2155
+ for (const id of targetIds) {
2156
+ const skillDef = manifestById.get(id);
2157
+ if (!skillDef) continue;
2158
+ const mirroredTo = skillDef.ides.filter((i) => ides.includes(i));
2159
+ lock.skills[id] = {
2160
+ version: skillDef.version,
2161
+ from: packageName,
2162
+ installedAt,
2163
+ scope,
2164
+ mirroredTo
2165
+ };
2166
+ }
2167
+ await writeSkillsLock(projectRoot, lock);
2168
+ return {
2169
+ status: "updated",
2170
+ packageName,
2171
+ version: manifest.version,
2172
+ ides,
2173
+ scope,
2174
+ updatedSkillIds: targetIds,
2175
+ skippedSkillIds,
2176
+ summary: result.summary,
2177
+ resources: result.resources
2178
+ };
2179
+ }
2180
+
2181
+ // src/commands/skills/update.ts
2182
+ var require5 = createRequire4(import.meta.url);
2183
+ var SKILLS_PACKAGE2 = "@teamix-evo/skills";
2184
+ var updateCommand2 = new Command10("update").description(
2185
+ "\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"
2186
+ ).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
2187
  try {
1839
2188
  const ide = detectIde();
1840
2189
  const cwd = ide.getProjectRoot();
@@ -1842,95 +2191,101 @@ var updateCommand2 = new Command9("update").description("\u66F4\u65B0\u5DF2\u5B8
1842
2191
  if (projectRoot !== cwd) {
1843
2192
  logger.info(`Using global skills meta root: ${projectRoot}`);
1844
2193
  }
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({
2194
+ await printVersionBanner();
2195
+ const result = await runSkillsUpdate({
1871
2196
  projectRoot,
1872
- manifest,
1873
- data,
1874
- packageRoot,
1875
- ides,
1876
- scope
2197
+ names: names.length > 0 ? names : void 0,
2198
+ dryRun: opts.dryRun
1877
2199
  });
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
- };
2200
+ switch (result.status) {
2201
+ case "no-skills":
2202
+ logger.error(
2203
+ 'Skills not added. Run "teamix-evo skills init" first.'
2204
+ );
2205
+ process.exitCode = 1;
2206
+ return;
2207
+ case "no-changes":
2208
+ logger.success(
2209
+ `Already up-to-date (skills package v${result.version}).`
2210
+ );
2211
+ logger.info(
2212
+ ` Checked: ${result.checkedSkillIds.join(", ") || "(none)"}`
2213
+ );
2214
+ return;
2215
+ case "dry-run":
2216
+ logger.info(
2217
+ `Plan (${result.currentVersion} \u2192 ${result.availableVersion}):`
2218
+ );
2219
+ if (result.plan.length === 0) {
2220
+ logger.info(" (no skills to update)");
2221
+ } else {
2222
+ for (const item of result.plan) {
2223
+ logger.info(formatPlanItem(item));
2224
+ }
2225
+ }
2226
+ logger.info("");
2227
+ logger.info("Re-run without --dry-run to apply.");
2228
+ return;
2229
+ case "updated": {
2230
+ const { summary } = result;
2231
+ logger.success(
2232
+ `Skills updated to v${result.version} (${result.updatedSkillIds.length} skill(s)).`
2233
+ );
2234
+ if (result.updatedSkillIds.length > 0) {
2235
+ logger.info(
2236
+ ` Updated: ${result.updatedSkillIds.join(", ")}`
2237
+ );
2238
+ }
2239
+ if (result.skippedSkillIds.length > 0) {
2240
+ logger.info(
2241
+ ` Skipped: ${result.skippedSkillIds.join(", ")} (scope mismatch / removed upstream)`
2242
+ );
2243
+ }
2244
+ logger.info(` Created: ${summary.created}`);
2245
+ logger.info(` Overwritten: ${summary.overwritten}`);
2246
+ logger.info(` Managed: ${summary.managed}`);
2247
+ logger.info(` Skipped: ${summary.skipped}`);
2248
+ return;
2249
+ }
1912
2250
  }
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
2251
  } catch (err) {
1921
2252
  logger.error(`Failed to update skills: ${err.message}`);
1922
2253
  logger.debug(err.stack ?? "");
1923
2254
  process.exitCode = 1;
1924
2255
  }
1925
2256
  });
2257
+ function formatPlanItem(item) {
2258
+ const tag = item.action === "up-to-date" ? " =" : item.strategy === "frozen" ? " \u2298 " : item.strategy === "managed" ? " \u2295 " : " \u2192 ";
2259
+ const ver = item.action === "up-to-date" ? `v${item.current} (no change)` : `v${item.current} \u2192 v${item.next} [${item.strategy}]`;
2260
+ return `${tag}${item.id} ${ver}`;
2261
+ }
2262
+ async function printVersionBanner() {
2263
+ let cliVersion;
2264
+ try {
2265
+ const pkg = require5("../package.json");
2266
+ cliVersion = pkg.version;
2267
+ } catch {
2268
+ }
2269
+ try {
2270
+ const { manifest } = await loadSkillsData(SKILLS_PACKAGE2);
2271
+ if (cliVersion) {
2272
+ logger.info(
2273
+ `teamix-evo CLI v${cliVersion} \xB7 skills package v${manifest.version}`
2274
+ );
2275
+ } else {
2276
+ logger.info(`skills package v${manifest.version}`);
2277
+ }
2278
+ } catch {
2279
+ }
2280
+ }
1926
2281
 
1927
2282
  // src/commands/skills/uninstall.ts
1928
- import { Command as Command10 } from "commander";
1929
- import * as prompts3 from "@clack/prompts";
2283
+ import { Command as Command11 } from "commander";
2284
+ import * as prompts4 from "@clack/prompts";
1930
2285
  import * as path13 from "path";
1931
2286
  import * as fs10 from "fs/promises";
1932
2287
  var SKILLS_PACKAGE3 = "@teamix-evo/skills";
1933
- var uninstallCommand2 = new Command10("uninstall").description(
2288
+ var uninstallCommand2 = new Command11("uninstall").description(
1934
2289
  "\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
2290
  ).argument(
1936
2291
  "[ids...]",
@@ -1984,11 +2339,11 @@ async function runFullUninstall(args) {
1984
2339
  `Will remove ${resources.length} skill file(s) installed by ${SKILLS_PACKAGE3}.`
1985
2340
  );
1986
2341
  if (!opts.yes) {
1987
- const confirm4 = await prompts3.confirm({
2342
+ const confirm5 = await prompts4.confirm({
1988
2343
  message: "\u786E\u8BA4\u5378\u8F7D\uFF1F\u6B64\u64CD\u4F5C\u4F1A\u5220\u9664\u4E0A\u8FF0\u6587\u4EF6\u3002",
1989
2344
  initialValue: false
1990
2345
  });
1991
- if (prompts3.isCancel(confirm4) || !confirm4) {
2346
+ if (prompts4.isCancel(confirm5) || !confirm5) {
1992
2347
  logger.info("Cancelled.");
1993
2348
  return;
1994
2349
  }
@@ -2053,11 +2408,11 @@ async function runPartialUninstall(args) {
2053
2408
  `Will remove ${matched.length} skill(s): ${matched.join(", ")} (${toRemove.length} file(s)).`
2054
2409
  );
2055
2410
  if (!opts.yes) {
2056
- const confirm4 = await prompts3.confirm({
2411
+ const confirm5 = await prompts4.confirm({
2057
2412
  message: "\u786E\u8BA4\u5378\u8F7D\uFF1F\u6B64\u64CD\u4F5C\u4F1A\u5220\u9664\u4E0A\u8FF0\u6587\u4EF6\u3002",
2058
2413
  initialValue: false
2059
2414
  });
2060
- if (prompts3.isCancel(confirm4) || !confirm4) {
2415
+ if (prompts4.isCancel(confirm5) || !confirm5) {
2061
2416
  logger.info("Cancelled.");
2062
2417
  return;
2063
2418
  }
@@ -2174,17 +2529,17 @@ function dedupe(values) {
2174
2529
  }
2175
2530
 
2176
2531
  // src/commands/skills/sync.ts
2177
- import { Command as Command11 } from "commander";
2532
+ import { Command as Command12 } from "commander";
2178
2533
 
2179
2534
  // src/core/skills-sync.ts
2180
2535
  import * as path14 from "path";
2181
2536
  import * as fs11 from "fs/promises";
2182
- import { createRequire as createRequire4 } from "module";
2537
+ import { createRequire as createRequire5 } from "module";
2183
2538
  import { loadSkillsPackageManifest as loadSkillsPackageManifest2 } from "@teamix-evo/registry";
2184
- var require5 = createRequire4(import.meta.url);
2539
+ var require6 = createRequire5(import.meta.url);
2185
2540
  async function readSkillMetaFromUpstream(skillId) {
2186
2541
  try {
2187
- const pkgJson = require5.resolve("@teamix-evo/skills/package.json");
2542
+ const pkgJson = require6.resolve("@teamix-evo/skills/package.json");
2188
2543
  const packageRoot = path14.dirname(pkgJson);
2189
2544
  const manifest = await loadSkillsPackageManifest2(packageRoot);
2190
2545
  const entry = manifest.skills.find((s) => s.id === skillId);
@@ -2283,7 +2638,7 @@ async function refreshMirrorRecords(projectRoot, newMirrorRecords) {
2283
2638
  }
2284
2639
 
2285
2640
  // src/commands/skills/sync.ts
2286
- var syncCommand = new Command11("sync").description(
2641
+ var syncCommand = new Command12("sync").description(
2287
2642
  "\u628A .teamix-evo/skills/ \u4E0B\u7684\u6E90\u91CD\u65B0\u955C\u50CF\u5230 IDE \u8DEF\u5F84\uFF08.qoder / .claude\uFF09"
2288
2643
  ).argument(
2289
2644
  "[names...]",
@@ -2302,8 +2657,8 @@ var syncCommand = new Command11("sync").description(
2302
2657
  if (projectRoot !== cwd) {
2303
2658
  logger.info(`Using global skills meta root: ${projectRoot}`);
2304
2659
  }
2305
- const ides = opts.ide ? parseIdeList2(opts.ide) : void 0;
2306
- const scope = opts.scope ? parseScope2(opts.scope) : void 0;
2660
+ const ides = opts.ide ? parseIdeList3(opts.ide) : void 0;
2661
+ const scope = opts.scope ? parseScope3(opts.scope) : void 0;
2307
2662
  const result = await runSkillsSync({
2308
2663
  projectRoot,
2309
2664
  ides,
@@ -2335,7 +2690,7 @@ var syncCommand = new Command11("sync").description(
2335
2690
  process.exitCode = 1;
2336
2691
  }
2337
2692
  });
2338
- function parseIdeList2(input) {
2693
+ function parseIdeList3(input) {
2339
2694
  const parts = input.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
2340
2695
  const result = [];
2341
2696
  for (const p of parts) {
@@ -2349,14 +2704,14 @@ function parseIdeList2(input) {
2349
2704
  }
2350
2705
  return result;
2351
2706
  }
2352
- function parseScope2(input) {
2707
+ function parseScope3(input) {
2353
2708
  const v = input.toLowerCase();
2354
2709
  if (v === "project" || v === "global") return v;
2355
2710
  throw new Error(`Invalid --scope: "${input}". Expected project | global.`);
2356
2711
  }
2357
2712
 
2358
2713
  // src/commands/skills/doctor.ts
2359
- import { Command as Command12 } from "commander";
2714
+ import { Command as Command13 } from "commander";
2360
2715
 
2361
2716
  // src/core/skills-doctor.ts
2362
2717
  import * as path15 from "path";
@@ -2375,7 +2730,7 @@ async function runSkillsDoctor(options) {
2375
2730
  kind: "missing-source",
2376
2731
  skillId,
2377
2732
  path: sourceDir,
2378
- detail: 'Run "teamix-evo skills add" to reinstall.'
2733
+ detail: 'Run "teamix-evo skills init" to reinstall.'
2379
2734
  });
2380
2735
  continue;
2381
2736
  }
@@ -2445,7 +2800,7 @@ async function dirExists2(p) {
2445
2800
  }
2446
2801
 
2447
2802
  // src/commands/skills/doctor.ts
2448
- var doctorCommand = new Command12("doctor").description(
2803
+ var doctorCommand = new Command13("doctor").description(
2449
2804
  "\u68C0\u67E5 .teamix-evo/skills/ \u6E90\u4E0E IDE \u955C\u50CF\u662F\u5426\u6F02\u79FB\uFF1B\u63D0\u793A\u5982\u4F55\u4FEE\u590D"
2450
2805
  ).action(async () => {
2451
2806
  try {
@@ -2458,7 +2813,7 @@ var doctorCommand = new Command12("doctor").description(
2458
2813
  const result = await runSkillsDoctor({ projectRoot });
2459
2814
  if (result.status === "no-skills") {
2460
2815
  logger.info(
2461
- 'No skills recorded. Run "teamix-evo skills add" first.'
2816
+ 'No skills recorded. Run "teamix-evo skills init" first.'
2462
2817
  );
2463
2818
  return;
2464
2819
  }
@@ -2484,9 +2839,10 @@ var doctorCommand = new Command12("doctor").description(
2484
2839
  });
2485
2840
 
2486
2841
  // src/commands/skills/index.ts
2487
- var skillsCommand = new Command13("skills").description(
2842
+ var skillsCommand = new Command14("skills").description(
2488
2843
  "\u7BA1\u7406 teamix-evo skills\uFF08\u5411 AI IDE \u6CE8\u5165\u6280\u80FD\uFF1Bsource-mirror \u6A21\u578B\u89C1 ADR 0013\uFF09"
2489
2844
  );
2845
+ skillsCommand.addCommand(initCommand2);
2490
2846
  skillsCommand.addCommand(addCommand);
2491
2847
  skillsCommand.addCommand(listCommand2);
2492
2848
  skillsCommand.addCommand(updateCommand2);
@@ -2495,11 +2851,11 @@ skillsCommand.addCommand(doctorCommand);
2495
2851
  skillsCommand.addCommand(uninstallCommand2);
2496
2852
 
2497
2853
  // src/commands/ui/index.ts
2498
- import { Command as Command17 } from "commander";
2854
+ import { Command as Command18 } from "commander";
2499
2855
 
2500
2856
  // src/commands/ui/init.ts
2501
- import { Command as Command14 } from "commander";
2502
- import * as prompts4 from "@clack/prompts";
2857
+ import { Command as Command15 } from "commander";
2858
+ import * as prompts5 from "@clack/prompts";
2503
2859
 
2504
2860
  // src/core/ui-init.ts
2505
2861
  var DEFAULT_UI_ALIASES = {
@@ -2556,7 +2912,7 @@ async function runUiInit(options) {
2556
2912
  }
2557
2913
 
2558
2914
  // src/commands/ui/init.ts
2559
- var initCommand2 = new Command14("init").description(
2915
+ var initCommand3 = new Command15("init").description(
2560
2916
  "\u521D\u59CB\u5316 teamix-evo ui \u914D\u7F6E\uFF08\u8BE2\u95EE aliases / iconLibrary / tsx / rsc\uFF09"
2561
2917
  ).option("-y, --yes", "\u4F7F\u7528\u9ED8\u8BA4\u503C\uFF0C\u8DF3\u8FC7\u4EA4\u4E92").option(
2562
2918
  "--components <path>",
@@ -2618,41 +2974,41 @@ async function resolveConfig(opts) {
2618
2974
  rsc: opts.rsc ?? false
2619
2975
  };
2620
2976
  }
2621
- const components = await prompts4.text({
2977
+ const components = await prompts5.text({
2622
2978
  message: "components \u8DEF\u5F84\uFF08\u6CE8\u5165\u6309\u94AE\u7B49\u7EC4\u4EF6\u6E90\u7801\u7684\u76EE\u5F55\uFF09",
2623
2979
  initialValue: opts.components ?? DEFAULT_UI_ALIASES.components
2624
2980
  });
2625
- if (prompts4.isCancel(components)) throw new Error("Cancelled by user.");
2626
- const hooks = await prompts4.text({
2981
+ if (prompts5.isCancel(components)) throw new Error("Cancelled by user.");
2982
+ const hooks = await prompts5.text({
2627
2983
  message: "hooks \u8DEF\u5F84",
2628
2984
  initialValue: opts.hooks ?? DEFAULT_UI_ALIASES.hooks
2629
2985
  });
2630
- if (prompts4.isCancel(hooks)) throw new Error("Cancelled by user.");
2631
- const utils = await prompts4.text({
2986
+ if (prompts5.isCancel(hooks)) throw new Error("Cancelled by user.");
2987
+ const utils = await prompts5.text({
2632
2988
  message: "utils \u8DEF\u5F84\uFF08cn \u7B49\u5DE5\u5177\uFF09",
2633
2989
  initialValue: opts.utils ?? DEFAULT_UI_ALIASES.utils
2634
2990
  });
2635
- if (prompts4.isCancel(utils)) throw new Error("Cancelled by user.");
2636
- const lib = await prompts4.text({
2991
+ if (prompts5.isCancel(utils)) throw new Error("Cancelled by user.");
2992
+ const lib = await prompts5.text({
2637
2993
  message: "lib \u8DEF\u5F84\uFF08\u5171\u4EAB\u4EE3\u7801\u6839\uFF09",
2638
2994
  initialValue: opts.lib ?? DEFAULT_UI_ALIASES.lib
2639
2995
  });
2640
- if (prompts4.isCancel(lib)) throw new Error("Cancelled by user.");
2641
- const iconLibrary = await prompts4.text({
2996
+ if (prompts5.isCancel(lib)) throw new Error("Cancelled by user.");
2997
+ const iconLibrary = await prompts5.text({
2642
2998
  message: "icon \u5E93\uFF08\u58F0\u660E\u6027\uFF0C\u7EC4\u4EF6\u6E90\u7801\u5DF2 hardcode lucide-react\uFF09",
2643
2999
  initialValue: opts.iconLibrary ?? "lucide"
2644
3000
  });
2645
- if (prompts4.isCancel(iconLibrary)) throw new Error("Cancelled by user.");
2646
- const tsxAns = await prompts4.confirm({
3001
+ if (prompts5.isCancel(iconLibrary)) throw new Error("Cancelled by user.");
3002
+ const tsxAns = await prompts5.confirm({
2647
3003
  message: "\u4F7F\u7528 TSX\uFF1F",
2648
3004
  initialValue: opts.tsx ?? true
2649
3005
  });
2650
- if (prompts4.isCancel(tsxAns)) throw new Error("Cancelled by user.");
2651
- const rscAns = await prompts4.confirm({
3006
+ if (prompts5.isCancel(tsxAns)) throw new Error("Cancelled by user.");
3007
+ const rscAns = await prompts5.confirm({
2652
3008
  message: "\u4F7F\u7528 React Server Components\uFF1F",
2653
3009
  initialValue: opts.rsc ?? false
2654
3010
  });
2655
- if (prompts4.isCancel(rscAns)) throw new Error("Cancelled by user.");
3011
+ if (prompts5.isCancel(rscAns)) throw new Error("Cancelled by user.");
2656
3012
  return {
2657
3013
  aliases: {
2658
3014
  components,
@@ -2669,16 +3025,16 @@ async function resolveConfig(opts) {
2669
3025
  }
2670
3026
 
2671
3027
  // src/commands/ui/add.ts
2672
- import { Command as Command15 } from "commander";
3028
+ import { Command as Command16 } from "commander";
2673
3029
 
2674
3030
  // src/core/ui-client.ts
2675
3031
  import * as path16 from "path";
2676
3032
  import * as fs13 from "fs/promises";
2677
- import { createRequire as createRequire5 } from "module";
3033
+ import { createRequire as createRequire6 } from "module";
2678
3034
  import { loadUiPackageManifest } from "@teamix-evo/registry";
2679
- var require6 = createRequire5(import.meta.url);
3035
+ var require7 = createRequire6(import.meta.url);
2680
3036
  function resolvePackageRoot2(packageName) {
2681
- const pkgJsonPath = require6.resolve(`${packageName}/package.json`);
3037
+ const pkgJsonPath = require7.resolve(`${packageName}/package.json`);
2682
3038
  return path16.dirname(pkgJsonPath);
2683
3039
  }
2684
3040
  async function loadUiData(packageName) {
@@ -2894,7 +3250,7 @@ function mergeResources(prior, next) {
2894
3250
  }
2895
3251
 
2896
3252
  // src/commands/ui/add.ts
2897
- var addCommand2 = new Command15("add").description(
3253
+ var addCommand2 = new Command16("add").description(
2898
3254
  "\u5B89\u88C5\u4E00\u4E2A\u6216\u591A\u4E2A ui entry\uFF08\u6309 id\uFF0C\u81EA\u52A8\u5C55\u5F00 registryDependencies\uFF09"
2899
3255
  ).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
3256
  "--include-deprecated",
@@ -2940,7 +3296,7 @@ var addCommand2 = new Command15("add").description(
2940
3296
  );
2941
3297
 
2942
3298
  // src/commands/ui/list.ts
2943
- import { Command as Command16 } from "commander";
3299
+ import { Command as Command17 } from "commander";
2944
3300
 
2945
3301
  // src/core/ui-list.ts
2946
3302
  var DEFAULT_UI_PACKAGE2 = "@teamix-evo/ui";
@@ -2978,7 +3334,7 @@ async function runUiList(options) {
2978
3334
  }
2979
3335
 
2980
3336
  // 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(
3337
+ 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
3338
  "--include-deprecated",
2983
3339
  "\u540C\u65F6\u5217\u51FA\u5DF2\u5F52\u6863\u7684 deprecated entry\uFF08\u9ED8\u8BA4\u9690\u85CF\uFF0CADR 0028\uFF09"
2984
3340
  ).action(
@@ -3030,30 +3386,30 @@ var listCommand3 = new Command16("list").description("\u5217\u51FA @teamix-evo/u
3030
3386
  );
3031
3387
 
3032
3388
  // src/commands/ui/index.ts
3033
- var uiCommand = new Command17("ui").description(
3389
+ var uiCommand = new Command18("ui").description(
3034
3390
  "\u7BA1\u7406 teamix-evo ui \u7EC4\u4EF6\uFF08\u6E90\u7801\u6CE8\u5165\u5F0F\u5B89\u88C5\uFF0Cshadcn \u98CE\u683C\uFF09"
3035
3391
  );
3036
- uiCommand.addCommand(initCommand2);
3392
+ uiCommand.addCommand(initCommand3);
3037
3393
  uiCommand.addCommand(addCommand2);
3038
3394
  uiCommand.addCommand(listCommand3);
3039
3395
 
3040
3396
  // src/commands/biz-ui/index.ts
3041
- import { Command as Command21 } from "commander";
3397
+ import { Command as Command22 } from "commander";
3042
3398
 
3043
3399
  // src/commands/biz-ui/add.ts
3044
- import { Command as Command18 } from "commander";
3400
+ import { Command as Command19 } from "commander";
3045
3401
 
3046
3402
  // src/core/variant-ui-add.ts
3047
3403
  import * as path18 from "path";
3048
- import { createRequire as createRequire6 } from "module";
3404
+ import { createRequire as createRequire7 } from "module";
3049
3405
  import {
3050
3406
  loadUiPackageManifest as loadUiPackageManifest2,
3051
3407
  loadVariantUiPackageCatalog,
3052
3408
  loadVariantUiPackageManifest
3053
3409
  } from "@teamix-evo/registry";
3054
- var require7 = createRequire6(import.meta.url);
3410
+ var require8 = createRequire7(import.meta.url);
3055
3411
  function resolvePackageRoot3(packageName) {
3056
- const pkgJsonPath = require7.resolve(`${packageName}/package.json`);
3412
+ const pkgJsonPath = require8.resolve(`${packageName}/package.json`);
3057
3413
  return path18.dirname(pkgJsonPath);
3058
3414
  }
3059
3415
  async function runVariantUiAdd(packageName, options) {
@@ -3212,7 +3568,7 @@ async function listTemplatesEntries(variant, packageRoot) {
3212
3568
  }
3213
3569
 
3214
3570
  // src/commands/biz-ui/add.ts
3215
- var addCommand3 = new Command18("add").description(
3571
+ var addCommand3 = new Command19("add").description(
3216
3572
  "\u5B89\u88C5\u4E00\u4E2A\u6216\u591A\u4E2A\u4E1A\u52A1 UI \u7EC4\u4EF6(\u6309 id,\u81EA\u52A8\u5C55\u5F00 ui \u5305\u7684 registryDependencies)"
3217
3573
  ).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
3574
  async (ids, opts) => {
@@ -3261,8 +3617,8 @@ var addCommand3 = new Command18("add").description(
3261
3617
  );
3262
3618
 
3263
3619
  // 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) => {
3620
+ import { Command as Command20 } from "commander";
3621
+ 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
3622
  try {
3267
3623
  const result = await listBizUiEntries(opts.variant);
3268
3624
  logger.info(`${result.packageName}#${result.variant} entries:`);
@@ -3287,8 +3643,8 @@ var listCommand4 = new Command19("list").description("\u5217\u51FA\u6307\u5B9A\u
3287
3643
  });
3288
3644
 
3289
3645
  // 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 () => {
3646
+ import { Command as Command21 } from "commander";
3647
+ 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
3648
  try {
3293
3649
  const result = await listBizUiVariants();
3294
3650
  logger.info(`Available biz-ui variants in ${result.packageName}:`);
@@ -3310,7 +3666,7 @@ var listVariantsCommand2 = new Command20("list-variants").description("\u5217\u5
3310
3666
  });
3311
3667
 
3312
3668
  // src/commands/biz-ui/index.ts
3313
- var bizUiCommand = new Command21("biz-ui").description(
3669
+ var bizUiCommand = new Command22("biz-ui").description(
3314
3670
  "\u7BA1\u7406\u4E1A\u52A1 UI \u7EC4\u4EF6(\u53D8\u4F53\u611F\u77E5 \u2014 \u4E0E design / templates \u540C\u53D8\u4F53\u540D\u7A7A\u95F4)"
3315
3671
  );
3316
3672
  bizUiCommand.addCommand(addCommand3);
@@ -3318,11 +3674,11 @@ bizUiCommand.addCommand(listCommand4);
3318
3674
  bizUiCommand.addCommand(listVariantsCommand2);
3319
3675
 
3320
3676
  // src/commands/templates/index.ts
3321
- import { Command as Command25 } from "commander";
3677
+ import { Command as Command26 } from "commander";
3322
3678
 
3323
3679
  // src/commands/templates/add.ts
3324
- import { Command as Command22 } from "commander";
3325
- var addCommand4 = new Command22("add").description(
3680
+ import { Command as Command23 } from "commander";
3681
+ var addCommand4 = new Command23("add").description(
3326
3682
  "\u5B89\u88C5\u4E00\u4E2A\u6216\u591A\u4E2A\u9875\u9762\u6A21\u677F(\u6309 id,\u81EA\u52A8\u5C55\u5F00 ui \u5305\u7684 registryDependencies)"
3327
3683
  ).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
3684
  async (ids, opts) => {
@@ -3371,8 +3727,8 @@ var addCommand4 = new Command22("add").description(
3371
3727
  );
3372
3728
 
3373
3729
  // 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) => {
3730
+ import { Command as Command24 } from "commander";
3731
+ 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
3732
  try {
3377
3733
  const result = await listTemplatesEntries(opts.variant);
3378
3734
  logger.info(`${result.packageName}#${result.variant} entries:`);
@@ -3397,8 +3753,8 @@ var listCommand5 = new Command23("list").description("\u5217\u51FA\u6307\u5B9A\u
3397
3753
  });
3398
3754
 
3399
3755
  // 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 () => {
3756
+ import { Command as Command25 } from "commander";
3757
+ 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
3758
  try {
3403
3759
  const result = await listTemplatesVariants();
3404
3760
  logger.info(`Available templates variants in ${result.packageName}:`);
@@ -3420,7 +3776,7 @@ var listVariantsCommand3 = new Command24("list-variants").description("\u5217\u5
3420
3776
  });
3421
3777
 
3422
3778
  // src/commands/templates/index.ts
3423
- var templatesCommand = new Command25("templates").description(
3779
+ var templatesCommand = new Command26("templates").description(
3424
3780
  "\u7BA1\u7406\u9875\u9762\u6A21\u677F(\u53D8\u4F53\u611F\u77E5 \u2014 \u4E0E design / biz-ui \u540C\u53D8\u4F53\u540D\u7A7A\u95F4)"
3425
3781
  );
3426
3782
  templatesCommand.addCommand(addCommand4);
@@ -3428,24 +3784,26 @@ templatesCommand.addCommand(listCommand5);
3428
3784
  templatesCommand.addCommand(listVariantsCommand3);
3429
3785
 
3430
3786
  // src/commands/logs/index.ts
3431
- import { Command as Command28 } from "commander";
3787
+ import { Command as Command29 } from "commander";
3432
3788
 
3433
3789
  // src/commands/logs/analyze.ts
3434
- import { Command as Command26 } from "commander";
3790
+ import { Command as Command27 } from "commander";
3435
3791
  import { readFileSync, readdirSync, existsSync as existsSync2, statSync } from "fs";
3436
3792
  import { resolve as resolve3, join as join17 } from "path";
3437
3793
  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(
3794
+ var logsAnalyzeCommand = new Command27("analyze").description(
3795
+ "\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"
3796
+ ).option("--dir <path>", "log \u76EE\u5F55 (\u9ED8\u8BA4 <project>/.teamix-evo/logs/ai)").option(
3441
3797
  "--days <n>",
3442
3798
  "\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
3799
  ).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"));
3800
+ const baseDir = resolve3(
3801
+ opts.dir ?? join17(process.cwd(), ".teamix-evo", "logs", "ai")
3802
+ );
3445
3803
  if (!existsSync2(baseDir)) {
3446
3804
  logger.warn(`No log directory at ${baseDir}.`);
3447
3805
  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"
3806
+ "\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
3807
  );
3450
3808
  return;
3451
3809
  }
@@ -3615,18 +3973,20 @@ function parseIntOrUndef(v) {
3615
3973
  }
3616
3974
 
3617
3975
  // src/commands/logs/trace.ts
3618
- import { Command as Command27 } from "commander";
3976
+ import { Command as Command28 } from "commander";
3619
3977
  import { readFileSync as readFileSync2, readdirSync as readdirSync2, existsSync as existsSync3, statSync as statSync2 } from "fs";
3620
3978
  import { resolve as resolve4, join as join18 } from "path";
3621
3979
  var DATE_DIR_RE2 = /^\d{4}-\d{2}-\d{2}$/;
3622
- var logsTraceCommand = new Command27("trace").description(
3980
+ var logsTraceCommand = new Command28("trace").description(
3623
3981
  "\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"));
3982
+ ).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) => {
3983
+ const baseDir = resolve4(
3984
+ opts.dir ?? join18(process.cwd(), ".teamix-evo", "logs", "ai")
3985
+ );
3626
3986
  if (!existsSync3(baseDir)) {
3627
3987
  logger.warn(`No log directory at ${baseDir}.`);
3628
3988
  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"
3989
+ "\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
3990
  );
3631
3991
  return;
3632
3992
  }
@@ -3778,7 +4138,9 @@ function printTrace(baseDir, r) {
3778
4138
  logger.info("");
3779
4139
  for (const c of s.chains) {
3780
4140
  logger.info(
3781
- `[${formatTime(c.promptTs)}] \u{1F4AC} Prompt: ${quote(truncate(c.prompt, 200))}`
4141
+ `[${formatTime(c.promptTs)}] \u{1F4AC} Prompt: ${quote(
4142
+ truncate(c.prompt, 200)
4143
+ )}`
3782
4144
  );
3783
4145
  for (const step of c.steps) {
3784
4146
  logger.info(` ${formatStep(step)}`);
@@ -3825,16 +4187,175 @@ function parseIntOrUndef2(v) {
3825
4187
  }
3826
4188
 
3827
4189
  // 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"
4190
+ var logsCommand = new Command29("logs").description(
4191
+ "\u67E5\u8BE2 vibe-logger \u8F93\u51FA (.teamix-evo/logs/ai/**/*.jsonl) \u2014 AI \u8C03\u7528\u94FE\u5206\u6790"
3830
4192
  );
3831
4193
  logsCommand.addCommand(logsAnalyzeCommand);
3832
4194
  logsCommand.addCommand(logsTraceCommand);
3833
4195
 
4196
+ // src/commands/lint/index.ts
4197
+ import { Command as Command31 } from "commander";
4198
+
4199
+ // src/commands/lint/init.ts
4200
+ import { Command as Command30 } from "commander";
4201
+ import * as prompts6 from "@clack/prompts";
4202
+
4203
+ // src/core/lint-init.ts
4204
+ import * as path19 from "path";
4205
+ import * as fs15 from "fs";
4206
+ import { execa } from "execa";
4207
+ var ESLINT_CONFIG_CONTENT = `/**
4208
+ * teamix-evo consumer ESLint preset \u2014 9 token-discipline rules.
4209
+ * - Repo-wide: no-color-literal / no-arbitrary-tw-value / no-raw-color-scale /
4210
+ * no-large-radius / prefer-gap-over-space / no-manual-dark-classnames /
4211
+ * dialog-must-have-title (all error)
4212
+ * - src/components/ui/** only: no-relative-ui-import / icon-from-lucide (error)
4213
+ *
4214
+ * See ADR 0008 / docs/principles.md \xA7P4.
4215
+ */
4216
+ import consumerPreset from '@teamix-evo/eslint-config/presets/consumer';
4217
+
4218
+ export default [...consumerPreset];
4219
+ `;
4220
+ var STYLELINT_CONFIG_CONTENT = `/** @type {import('stylelint').Config} */
4221
+ module.exports = {
4222
+ extends: ['@teamix-evo/stylelint-config/presets/consumer'],
4223
+ };
4224
+ `;
4225
+ var ESLINT_DEPS = [
4226
+ "@teamix-evo/eslint-config",
4227
+ "eslint",
4228
+ "@typescript-eslint/parser"
4229
+ ];
4230
+ var STYLELINT_DEPS = ["@teamix-evo/stylelint-config", "stylelint"];
4231
+ async function runLintInit(options) {
4232
+ const { projectRoot, skipInstall } = options;
4233
+ const eslintConfigPath = path19.join(projectRoot, "eslint.config.js");
4234
+ const stylelintConfigPath = path19.join(projectRoot, "stylelint.config.cjs");
4235
+ const eslintExists = await fileExists(eslintConfigPath);
4236
+ const stylelintExists = await fileExists(stylelintConfigPath);
4237
+ if (eslintExists && stylelintExists) {
4238
+ return { status: "already-initialized" };
4239
+ }
4240
+ if (!skipInstall) {
4241
+ const depsToInstall = [
4242
+ ...eslintExists ? [] : ESLINT_DEPS,
4243
+ ...stylelintExists ? [] : STYLELINT_DEPS
4244
+ ];
4245
+ if (depsToInstall.length > 0) {
4246
+ const pm = detectPm(projectRoot);
4247
+ const args = pm === "yarn" ? ["add", "--dev", ...depsToInstall] : pm === "pnpm" ? ["add", "-D", ...depsToInstall] : ["install", "--save-dev", ...depsToInstall];
4248
+ logger.info(`Installing lint deps via ${pm}...`);
4249
+ await execa(pm, args, { cwd: projectRoot, stdio: "inherit" });
4250
+ }
4251
+ }
4252
+ let wroteEslint = false;
4253
+ let wroteStylelint = false;
4254
+ if (!eslintExists) {
4255
+ await writeFileSafe(eslintConfigPath, ESLINT_CONFIG_CONTENT);
4256
+ logger.debug(`Wrote eslint.config.js \u2192 ${eslintConfigPath}`);
4257
+ wroteEslint = true;
4258
+ }
4259
+ if (!stylelintExists) {
4260
+ await writeFileSafe(stylelintConfigPath, STYLELINT_CONFIG_CONTENT);
4261
+ logger.debug(`Wrote stylelint.config.cjs \u2192 ${stylelintConfigPath}`);
4262
+ wroteStylelint = true;
4263
+ }
4264
+ await patchPackageJsonScripts(projectRoot);
4265
+ return {
4266
+ status: "installed",
4267
+ eslint: wroteEslint,
4268
+ stylelint: wroteStylelint
4269
+ };
4270
+ }
4271
+ function detectPm(projectRoot) {
4272
+ if (fs15.existsSync(path19.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
4273
+ if (fs15.existsSync(path19.join(projectRoot, "yarn.lock"))) return "yarn";
4274
+ return "npm";
4275
+ }
4276
+ async function patchPackageJsonScripts(projectRoot) {
4277
+ const pkgPath = path19.join(projectRoot, "package.json");
4278
+ const raw = await readFileOrNull(pkgPath);
4279
+ if (!raw) return;
4280
+ let pkg;
4281
+ try {
4282
+ pkg = JSON.parse(raw);
4283
+ } catch {
4284
+ return;
4285
+ }
4286
+ const scripts = pkg.scripts ?? {};
4287
+ let changed = false;
4288
+ if (!scripts.lint) {
4289
+ scripts.lint = "eslint src/";
4290
+ changed = true;
4291
+ }
4292
+ if (!scripts["lint:css"]) {
4293
+ scripts["lint:css"] = "stylelint 'src/**/*.css'";
4294
+ changed = true;
4295
+ }
4296
+ if (changed) {
4297
+ pkg.scripts = scripts;
4298
+ await writeFileSafe(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
4299
+ logger.debug("Patched package.json scripts with lint / lint:css");
4300
+ }
4301
+ }
4302
+
4303
+ // src/commands/lint/init.ts
4304
+ var initCommand4 = new Command30("init").description(
4305
+ "\u521D\u59CB\u5316 ESLint + Stylelint \u5DE5\u7A0B\u89C4\u8303\uFF08\u5B89\u88C5\u4F9D\u8D56 + \u751F\u6210\u914D\u7F6E\u6587\u4EF6 + \u6CE8\u5165 scripts\uFF09"
4306
+ ).option("-y, --yes", "\u8DF3\u8FC7\u786E\u8BA4\uFF0C\u76F4\u63A5\u6267\u884C").action(async (opts) => {
4307
+ try {
4308
+ const ide = detectIde();
4309
+ const projectRoot = ide.getProjectRoot();
4310
+ if (!hasPackageJson(projectRoot)) {
4311
+ logger.error(
4312
+ "No package.json found in current directory. Please run this command in a valid project root."
4313
+ );
4314
+ process.exit(1);
4315
+ }
4316
+ if (!opts.yes) {
4317
+ const shouldContinue = await prompts6.confirm({
4318
+ 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"
4319
+ });
4320
+ if (prompts6.isCancel(shouldContinue) || !shouldContinue) {
4321
+ logger.info("Cancelled.");
4322
+ return;
4323
+ }
4324
+ }
4325
+ const result = await runLintInit({ projectRoot });
4326
+ if (result.status === "already-initialized") {
4327
+ logger.warn(
4328
+ "Lint already initialized. eslint.config.js and stylelint.config.cjs both exist."
4329
+ );
4330
+ return;
4331
+ }
4332
+ logger.success("Lint initialized.");
4333
+ if (result.eslint) {
4334
+ logger.info(" + eslint.config.js");
4335
+ }
4336
+ if (result.stylelint) {
4337
+ logger.info(" + stylelint.config.cjs");
4338
+ }
4339
+ logger.info("");
4340
+ logger.info('Run "npm run lint" to check JSX/TSX token discipline.');
4341
+ logger.info('Run "npm run lint:css" to check CSS token discipline.');
4342
+ } catch (err) {
4343
+ logger.error(`Failed to initialize lint: ${err.message}`);
4344
+ logger.debug(err.stack ?? "");
4345
+ process.exitCode = 1;
4346
+ }
4347
+ });
4348
+
4349
+ // src/commands/lint/index.ts
4350
+ var lintCommand = new Command31("lint").description(
4351
+ "\u7BA1\u7406\u5DE5\u7A0B\u89C4\u8303\uFF08ESLint + Stylelint token-discipline \u89C4\u5219\u96C6\uFF09"
4352
+ );
4353
+ lintCommand.addCommand(initCommand4);
4354
+
3834
4355
  // src/index.ts
3835
- var require8 = createRequire7(import.meta.url);
3836
- var { version } = require8("../package.json");
3837
- var program = new Command29();
4356
+ var require9 = createRequire8(import.meta.url);
4357
+ var { version } = require9("../package.json");
4358
+ var program = new Command32();
3838
4359
  program.name("teamix-evo").description("Where ideas evolve. \u2014 AI Coding \u5957\u4EF6").version(version);
3839
4360
  program.addCommand(tokensCommand);
3840
4361
  program.addCommand(skillsCommand);
@@ -3842,5 +4363,11 @@ program.addCommand(uiCommand);
3842
4363
  program.addCommand(bizUiCommand);
3843
4364
  program.addCommand(templatesCommand);
3844
4365
  program.addCommand(logsCommand);
4366
+ program.addCommand(lintCommand);
4367
+ function enableHelpAfterError(cmd) {
4368
+ cmd.showHelpAfterError(true);
4369
+ for (const child of cmd.commands) enableHelpAfterError(child);
4370
+ }
4371
+ enableHelpAfterError(program);
3845
4372
  program.parse();
3846
4373
  //# sourceMappingURL=index.js.map