teamix-evo 0.2.0 → 0.3.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/README.md CHANGED
@@ -16,41 +16,37 @@ CLI 是 Teamix Evo 的**执行层**,用户通过 `npx teamix-evo` 或全局安
16
16
  ```
17
17
  packages/cli/
18
18
  ├── src/
19
- │ ├── index.ts # 入口:Commander 注册
19
+ │ ├── index.ts # 入口:Commander 注册
20
20
  │ ├── commands/
21
- │ │ ├── design/
22
- │ │ │ ├── index.ts # design 命令组
23
- │ │ ├── init.ts # design init [variant]
24
- │ │ │ ├── update.ts # design update
25
- │ │ └── list.ts # design list
26
- ├── skills/
27
- │ │ ├── index.ts # skills 命令组
28
- │ │ ├── add.ts # skills add [name...]
29
- │ │ ├── list.ts # skills list
30
- │ │ ├── update.ts # skills update
31
- │ │ │ └── uninstall.ts # skills uninstall
32
- │ │ └── ui/
33
- │ │ ├── index.ts # ui 命令组
34
- │ │ ├── init.ts # ui init
35
- │ │ ├── add.ts # ui add <id...>
36
- │ │ └── list.ts # ui list
37
- │ ├── core/
38
- │ │ ├── installer.ts # 资源安装引擎
39
- │ │ ├── updater.ts # 资源更新引擎(三策略处理)
21
+ │ │ ├── design/ # design init <variant> / list / list-variants
22
+ │ │ │ # / update(stub) / uninstall
23
+ │ │ ├── skills/ # source-mirror 模型见 ADR 0013
24
+ │ │ │ │ # add / list / update / sync / doctor / uninstall
25
+ │ │ └── ui/ # init / add / list
26
+ │ ├── core/ # 业务编排层(programmatic API,subpath 导出)
27
+ │ │ ├── design-init.ts # walk-and-merge 装机
28
+ │ │ ├── design-pack-classify.ts # 路径分类(W1.4 tokens 提层)
29
+ │ │ ├── installer.ts # UI 资源安装引擎
30
+ │ │ ├── updater.ts # 三策略更新引擎(frozen/regenerable/managed)
31
+ │ │ ├── ui-{add,init,list,client,installer}.ts
32
+ │ │ ├── skills-{add,client,installer,sync,doctor}.ts
40
33
  │ │ ├── registry-client.ts # 从 npm 包解析 variant
41
34
  │ │ └── state.ts # .teamix-evo/ 状态读写
42
35
  │ ├── ide/
43
36
  │ │ ├── IdeAdapter.ts # IDE 适配接口
44
- │ │ ├── QoderAdapter.ts # Qoder 适配实现
45
- │ │ └── index.ts # IDE 检测入口
37
+ │ │ ├── QoderAdapter.ts # Qoder 适配
38
+ │ │ ├── ClaudeAdapter.ts # Claude Code 适配
39
+ │ │ └── index.ts # detectIde / ALL_IDE_KINDS
46
40
  │ ├── utils/
47
- │ │ ├── fs.ts # 原子写入、备份、文件操作
48
- │ │ ├── hash.ts # SHA-256 哈希
41
+ │ │ ├── fs.ts # 原子写入、备份
42
+ │ │ ├── hash.ts # SHA-256
49
43
  │ │ ├── logger.ts # 分级彩色日志
50
44
  │ │ ├── path.ts # 路径解析、目录遍历
51
- │ │ └── template.ts # Handlebars 渲染(带缓存)
52
- └── __tests__/ # 单元测试
53
- ├── tsup.config.ts # 构建配置(单文件 ESM + shebang)
45
+ │ │ ├── template.ts # Handlebars 渲染(带缓存)
46
+ │ ├── transform-imports.ts # 假路径 @/ → 用户 alias
47
+ │ │ └── global-root.ts # ~/.teamix-evo-global 解析(scope=global 用)
48
+ │ └── __tests__/ # 10 份单测,见下方测试章节
49
+ ├── tsup.config.ts # 构建配置(双入口:bin + core subpath)
54
50
  ├── tsconfig.json
55
51
  └── package.json
56
52
  ```
@@ -74,7 +70,10 @@ pnpm --filter @teamix-evo/registry build
74
70
  pnpm --filter teamix-evo dev
75
71
  ```
76
72
 
77
- 构建产物为单文件 `dist/index.js`(ESM,带 `#!/usr/bin/env node` banner)。
73
+ 构建产物双入口(见 `tsup.config.ts`):
74
+
75
+ - `dist/index.js` — CLI bin(ESM,带 `#!/usr/bin/env node` banner,对应 `package.json#bin`)
76
+ - `dist/core/index.{js,d.ts}` — programmatic API(ESM + 类型,对应 `teamix-evo/core` subpath 导出,不带 banner)
78
77
 
79
78
  ### 3. 新增命令
80
79
 
@@ -114,10 +113,11 @@ export const myCommand = new Command('my-cmd')
114
113
 
115
114
  ### 5. IDE 适配
116
115
 
117
- 当前 MVP 仅支持 Qoder。扩展新 IDE
116
+ 当前支持 Qoder Claude Code(`QoderAdapter` / `ClaudeAdapter`),`detectIde()` 自动判断。扩展新 IDE:
118
117
 
119
- 1. 在 `src/ide/` 下新建 `XxxAdapter.ts`,实现 `IdeAdapter` 接口
118
+ 1. 在 `src/ide/` 下新建 `XxxAdapter.ts`,实现 `IdeAdapter` 接口
120
119
  2. 在 `src/ide/index.ts` 的 `detectIde()` 中添加检测逻辑
120
+ 3. 在 `ALL_IDE_KINDS` 与 `SkillIde` 类型中加上新 IDE 名
121
121
 
122
122
  ### 6. 测试
123
123
 
@@ -129,12 +129,18 @@ pnpm --filter teamix-evo test
129
129
  pnpm --filter teamix-evo test:watch
130
130
  ```
131
131
 
132
- 测试文件位于 `src/__tests__/`,覆盖:
132
+ 测试文件位于 `src/__tests__/`,覆盖:
133
133
 
134
- - `installer.test.ts` — 资源安装(plain / template / recursive)
135
- - `updater.test.ts` — 三种策略更新逻辑
136
- - `state.test.ts` — 配置文件读写
134
+ - `core-api.test.ts` — programmatic core API(runDesignInit / runSkillsAdd / runUiAdd)
135
+ - `design-init-skills-link.test.ts` — design init ↔ skills auto-install 联动
136
+ - `installer.test.ts` — UI 资源安装(frozen / regenerable)
137
+ - `ui-installer.test.ts` — UI 装机引擎(依赖图 / alias 转换)
138
+ - `skills-installer.test.ts` — skills 装机(source-mirror)
139
+ - `skills-sync-doctor.test.ts` — source ↔ mirror 漂移检测
140
+ - `updater.test.ts` — 三策略更新逻辑(ADR 0003)
141
+ - `state.test.ts` — `.teamix-evo/` 状态读写
137
142
  - `template.test.ts` — Handlebars 渲染
143
+ - `transform-imports.test.ts` — 假路径(@/)→ 用户 alias 转换
138
144
 
139
145
  ### 7. 类型检查 & 构建
140
146
 
@@ -162,22 +168,42 @@ TEAMIX_DEBUG=1 teamix-evo design init opentrek
162
168
 
163
169
  ## 命令参考
164
170
 
165
- | 命令 | 说明 |
166
- | ---------------------------------- | ------------------------------- |
167
- | `teamix-evo design init [variant]` | 初始化设计体系(默认 opentrek) |
168
- | `teamix-evo design update` | 更新已安装的设计资源 |
169
- | `teamix-evo design list` | 查看已安装信息 |
170
- | `teamix-evo skills add [name...]` | 装入 skills(全量/增量) |
171
- | `teamix-evo skills list` | 列出所有 skill 的安装状态 |
172
- | `teamix-evo skills update` | 升级已安装 skills |
173
- | `teamix-evo skills uninstall` | 卸载 skills |
174
- | `teamix-evo ui init` | 初始化 ui 组件环境 |
175
- | `teamix-evo ui add <id...>` | 安装指定 ui 组件源码 |
176
- | `teamix-evo ui list` | 列出可用/已安装 ui 组件 |
177
-
178
- 选项:
179
-
180
- - `--tailwind <v3|v4>` 指定 Tailwind CSS 版本(默认 v3)
171
+ | 命令 | 说明 |
172
+ | --------------------------------------------------- | ------------------------------------------------- |
173
+ | `teamix-evo design init <variant>` | 初始化设计体系(variant 必填) |
174
+ | `teamix-evo design list-variants` | 列出可用 variant |
175
+ | `teamix-evo design list` | 查看已装机的 variant |
176
+ | `teamix-evo design update` | 更新已装资源(stub,v0.7 见 ADR 0019) |
177
+ | `teamix-evo design uninstall` | 卸载已装 design |
178
+ | `teamix-evo skills add [name...]` | skills(写源 + 镜像 IDE);不传 = 全装 |
179
+ | `teamix-evo skills list` | 列出所有 skill 的安装状态 |
180
+ | `teamix-evo skills update` | 升级 skills(保留 managed 改动) |
181
+ | `teamix-evo skills sync [name...]` | IDE 镜像(漂移恢复用) |
182
+ | `teamix-evo skills doctor` | 检测源/镜像漂移(ADR 0013) |
183
+ | `teamix-evo skills uninstall` | 卸载 skills(源 + 镜像 + lock) |
184
+ | `teamix-evo ui init` | 初始化 ui 配置(aliases / iconLibrary / tsx / rsc) |
185
+ | `teamix-evo ui add <id...>` | 安装指定 ui 组件源码 |
186
+ | `teamix-evo ui list [--installed]` | 列出可用/已安装 ui 组件 |
187
+ | `teamix-evo biz-ui list-variants` | 列出 biz-ui 包内提供的业务变体 |
188
+ | `teamix-evo biz-ui add <id...> --variant <name>` | 安装变体感知业务组件(`--variant` 必填) |
189
+ | `teamix-evo templates list-variants` | 列出 templates 包内提供的页面模板变体 |
190
+ | `teamix-evo templates add <id...> --variant <name>` | 安装变体感知页面模板(`--variant` 必填) |
191
+
192
+ > 占位组件 → 真组件的升级流程**不是** CLI 子命令,由
193
+ > [`teamix-evo-ui-upgrade`](../../packages/skills/skills/teamix-evo-ui-upgrade/SKILL.md)
194
+ > skill 在 IDE 内驱动,底层仍调用 `teamix-evo ui add`。
195
+
196
+ ### 全局装 skill(`--scope global`)
197
+
198
+ `skills add` 支持 `--scope global` 装到 IDE 全局(`~/.qoder/skills/` + `~/.claude/skills/`)。当 cwd 不是 Teamix Evo 项目时,工具会自动把元数据写到 `~/.teamix-evo-global/`,不污染当前目录。
199
+
200
+ ```bash
201
+ # Onboarding 推荐:全局装 manage skill
202
+ npx teamix-evo@latest skills add teamix-evo-manage --scope global --ide claude,qoder -y
203
+
204
+ # 后续维护(update / uninstall 等)需 cd 到全局元数据根
205
+ cd ~/.teamix-evo-global && npx teamix-evo skills update
206
+ ```
181
207
 
182
208
  ## 关键约定
183
209
 
@@ -1,26 +1,50 @@
1
- import { TailwindVersion, InstalledResource, SkillIde, SkillScope, UiAliases, UiEntry, VariantManifest, SkillsPackageManifest, UiPackageManifest, InstalledManifest, ProjectConfig } from '@teamix-evo/registry';
1
+ import { InstalledResource, SkillIde, SkillScope, UiAliases, UiEntry, VariantManifest, SkillsPackageManifest, SkillEntry, UiPackageManifest, InstalledManifest, ProjectConfig } from '@teamix-evo/registry';
2
2
  export { InstalledManifest, InstalledResource, ProjectConfig, SkillIde, SkillScope, TailwindVersion, UiAliases } from '@teamix-evo/registry';
3
3
 
4
4
  interface RunDesignInitOptions {
5
5
  /** Absolute project root directory. */
6
6
  projectRoot: string;
7
- /** Design variant id, e.g. "opentrek". */
7
+ /** Design variant id (e.g. `"opentrek"`, `"uni-manager"`). */
8
8
  variant: string;
9
- /** Tailwind major version of the consuming project. */
10
- tailwind: TailwindVersion;
11
- /** IDE identifier written into config.json (e.g. "qoder", "claude"). */
9
+ /** IDE identifier written into config.json (e.g. `"qoder"`, `"claude"`). */
12
10
  ide: string;
13
- /** Override the design package name (defaults to "@teamix-evo/design"). */
11
+ /** Override the design package name (defaults to `"@teamix-evo/design"`). */
14
12
  packageName?: string;
13
+ /**
14
+ * Override resolution of the design package root. When provided, skips
15
+ * `require.resolve("<packageName>/package.json")`. Useful for tests that
16
+ * want to point at a fixture tree, and for embedding inside `create`
17
+ * where the package may not yet be installed in the consumer.
18
+ */
19
+ packageRoot?: string;
20
+ }
21
+ /**
22
+ * Outcome of the post-init skill auto-install step. `attempted` lists the skill
23
+ * ids we tried to install (baseline + variant overlay); `addedSkillIds` is what
24
+ * was actually installed (the rest were already present); `missing` lists skill
25
+ * ids that aren't in the manifest (warned, not fatal).
26
+ */
27
+ interface SkillsAutoInstallResult {
28
+ attempted: string[];
29
+ addedSkillIds: string[];
30
+ skippedSkillIds: string[];
31
+ missing: string[];
15
32
  }
16
33
  type RunDesignInitResult = {
17
34
  status: 'installed';
18
35
  packageName: string;
19
36
  variant: string;
20
37
  version: string;
21
- tailwind: TailwindVersion;
22
38
  count: number;
23
39
  resources: InstalledResource[];
40
+ /** Per ADR 0010 §4 diagnostics. */
41
+ merge: {
42
+ overrides: string[];
43
+ variantAdds: string[];
44
+ defaultPassThrough: string[];
45
+ };
46
+ /** Result of the auto-install of baseline + variant design-rules skills. */
47
+ skills?: SkillsAutoInstallResult;
24
48
  } | {
25
49
  status: 'already-initialized';
26
50
  existingVariant: string;
@@ -30,10 +54,11 @@ type RunDesignInitResult = {
30
54
  *
31
55
  * Side effects:
32
56
  * - Creates `<projectRoot>/.teamix-evo/`
33
- * - Writes `config.json` and `manifest.json`
34
- * - Installs design resources from the variant manifest into the project
57
+ * - Walks `default/` + `variants/<variant>/`, classifies each file by path
58
+ * convention, writes to consumer (skipping `frozen` files that already exist)
59
+ * - Writes `pack.lock.json`, `config.json`, `manifest.json` (installed)
35
60
  *
36
- * No interactive prompts, no `process.exit`. Throws on hard failure.
61
+ * No interactive prompts, no `process.exit`. Throws on hard failure (P8).
37
62
  */
38
63
  declare function runDesignInit(options: RunDesignInitOptions): Promise<RunDesignInitResult>;
39
64
 
@@ -213,6 +238,21 @@ interface InstallResult {
213
238
  */
214
239
  declare function installResources(options: InstallOptions): Promise<InstallResult>;
215
240
 
241
+ /**
242
+ * Source-mirror skills installer (per ADR 0013).
243
+ *
244
+ * Two-stage flow:
245
+ * 1. **writeSkillSources** — render upstream `<packageRoot>/<skill.source>` and
246
+ * write to `<projectRoot>/.teamix-evo/skills/<id>/` (the consumer-side
247
+ * source of truth, regenerable, in git).
248
+ * 2. **syncSkillsToIdes** — pure byte-for-byte copy from source dir to each
249
+ * requested IDE mirror path (`.qoder/skills/<id>/`, `.claude/skills/<id>/`).
250
+ * Mirrors are 100% derived; not subject to managed-region preservation.
251
+ *
252
+ * `installSkills` orchestrates both. `updateSkills` re-renders the source with
253
+ * managed-region preservation against the existing source (NOT the mirrors),
254
+ * then re-syncs.
255
+ */
216
256
  interface SkillInstallOptions {
217
257
  /** Project root directory */
218
258
  projectRoot: string;
@@ -234,13 +274,19 @@ interface SkillInstallResult {
234
274
  count: number;
235
275
  }
236
276
  /**
237
- * Install (or reinstall) all skills declared in the manifest, fanning out to the
238
- * intersection of requested IDEs and each skill's declared `ides`.
277
+ * Install (or reinstall) all skills declared in the manifest using the
278
+ * source-mirror flow. Returns InstalledResource records for both source files
279
+ * and IDE mirror files.
239
280
  */
240
281
  declare function installSkills(options: SkillInstallOptions): Promise<SkillInstallResult>;
241
282
  interface SkillUpdateOptions extends SkillInstallOptions {
242
- /** Existing installed records for the skills package */
243
- installed: InstalledResource[];
283
+ /**
284
+ * Optional: existing installed records (legacy parameter kept for callers that
285
+ * still pass it). The refactored updater consults the file-system source under
286
+ * `.teamix-evo/skills/<id>/` for managed-region preservation, so this is
287
+ * unused by the new flow. Callers should stop passing it.
288
+ */
289
+ installed?: InstalledResource[];
244
290
  }
245
291
  interface SkillUpdateResult {
246
292
  resources: InstalledResource[];
@@ -252,9 +298,41 @@ interface SkillUpdateResult {
252
298
  };
253
299
  }
254
300
  /**
255
- * Update skills according to their updateStrategy.
301
+ * Update skills with managed-region preservation applied at the SOURCE layer
302
+ * (not the mirrors). After source is rewritten, mirrors are re-synced cleanly.
256
303
  */
257
304
  declare function updateSkills(options: SkillUpdateOptions): Promise<SkillUpdateResult>;
305
+ /**
306
+ * Sync existing skill sources to the requested IDE mirror paths.
307
+ *
308
+ * Used by:
309
+ * - `skills add` (immediate mirror after source write — handled by installSkills)
310
+ * - `skills sync` (re-mirror after the user adds an IDE or moves machines)
311
+ * - `skills update` (re-mirror after source is rewritten)
312
+ *
313
+ * `onlyIds` lets the caller limit which skills are synced.
314
+ */
315
+ interface SkillSyncOptions {
316
+ projectRoot: string;
317
+ /** Skills present in the source dir to mirror (caller derives from lock). */
318
+ skills: ReadonlyArray<{
319
+ id: string;
320
+ name: string;
321
+ updateStrategy: SkillEntry['updateStrategy'];
322
+ }>;
323
+ ides: readonly SkillIde[];
324
+ scope: SkillScope;
325
+ onlyIds?: string[];
326
+ }
327
+ interface SkillSyncResult {
328
+ resources: InstalledResource[];
329
+ count: number;
330
+ }
331
+ /**
332
+ * Mirror existing source dirs (`.teamix-evo/skills/<id>/`) to the given IDE
333
+ * paths. Pure byte-for-byte copy — no rendering, no merge.
334
+ */
335
+ declare function syncSkillsToIdes(options: SkillSyncOptions): Promise<SkillSyncResult>;
258
336
  /**
259
337
  * Remove all installed skill files. Returns the absolute paths removed.
260
338
  */
@@ -361,4 +439,4 @@ declare function readInstalledManifest(projectRoot: string): Promise<InstalledMa
361
439
  */
362
440
  declare function writeInstalledManifest(projectRoot: string, manifest: InstalledManifest): Promise<void>;
363
441
 
364
- export { DEFAULT_UI_ALIASES, DEFAULT_UI_ICON_LIBRARY, type InstallOptions, type InstallResult, type RunDesignInitOptions, type RunDesignInitResult, type RunSkillsAddOptions, type RunSkillsAddResult, type RunUiAddOptions, type RunUiAddResult, type RunUiInitOptions, type RunUiInitResult, type RunUiListOptions, type RunUiListResult, type SkillInstallOptions, type SkillInstallResult, type SkillUpdateOptions, type SkillUpdateResult, type UiEntryListItem, type UiInstallOptions, type UiInstallResult, ensureTeamixDir, getTeamixDir, installResources, installSkills, installUiEntries, loadSkillsData, loadUiData, loadVariantData, readInstalledManifest, readProjectConfig, removeSkillFiles, removeUiFiles, runDesignInit, runSkillsAdd, runUiAdd, runUiInit, runUiList, updateSkills, writeInstalledManifest, writeProjectConfig };
442
+ export { DEFAULT_UI_ALIASES, DEFAULT_UI_ICON_LIBRARY, type InstallOptions, type InstallResult, type RunDesignInitOptions, type RunDesignInitResult, type RunSkillsAddOptions, type RunSkillsAddResult, type RunUiAddOptions, type RunUiAddResult, type RunUiInitOptions, type RunUiInitResult, type RunUiListOptions, type RunUiListResult, type SkillInstallOptions, type SkillInstallResult, type SkillSyncOptions, type SkillSyncResult, type SkillUpdateOptions, type SkillUpdateResult, type UiEntryListItem, type UiInstallOptions, type UiInstallResult, ensureTeamixDir, getTeamixDir, installResources, installSkills, installUiEntries, loadSkillsData, loadUiData, loadVariantData, readInstalledManifest, readProjectConfig, removeSkillFiles, removeUiFiles, runDesignInit, runSkillsAdd, runUiAdd, runUiInit, runUiList, syncSkillsToIdes, updateSkills, writeInstalledManifest, writeProjectConfig };