@teamix-evo/skills 0.2.0 → 0.4.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/README.md +18 -8
- package/_template/SKILL.md.hbs +14 -1
- package/manifest.json +79 -6
- package/package.json +7 -3
- package/src/teamix-evo-code-opentrek/SKILL.md +92 -0
- package/src/teamix-evo-code-opentrek/api-layering.md +225 -0
- package/src/teamix-evo-code-opentrek/checklist.md +173 -0
- package/src/teamix-evo-code-opentrek/error-and-loading.md +269 -0
- package/src/teamix-evo-code-opentrek/file-structure.md +273 -0
- package/src/teamix-evo-code-opentrek/forms-and-validation.md +220 -0
- package/src/teamix-evo-code-opentrek/reuse-first.md +130 -0
- package/src/teamix-evo-code-opentrek/routing-and-codesplit.md +298 -0
- package/src/teamix-evo-code-opentrek/testing.md +313 -0
- package/src/teamix-evo-code-uni-manager/SKILL.md +95 -0
- package/src/teamix-evo-code-uni-manager/api-layering.md +370 -0
- package/src/teamix-evo-code-uni-manager/checklist.md +193 -0
- package/src/teamix-evo-code-uni-manager/error-and-loading.md +389 -0
- package/src/teamix-evo-code-uni-manager/file-structure.md +339 -0
- package/src/teamix-evo-code-uni-manager/forms-and-validation.md +459 -0
- package/src/teamix-evo-code-uni-manager/reuse-first.md +188 -0
- package/src/teamix-evo-code-uni-manager/routing-and-codesplit.md +450 -0
- package/src/teamix-evo-code-uni-manager/testing.md +396 -0
- package/src/teamix-evo-design-opentrek/SKILL.md +71 -0
- package/src/teamix-evo-design-opentrek/boundaries.md +513 -0
- package/src/teamix-evo-design-opentrek/brand.md +154 -0
- package/src/teamix-evo-design-opentrek/checklist.md +83 -0
- package/src/teamix-evo-design-opentrek/components.md +245 -0
- package/src/teamix-evo-design-opentrek/flows.md +51 -0
- package/src/teamix-evo-design-opentrek/foundations.md +271 -0
- package/src/teamix-evo-design-opentrek/generation-flow.md +185 -0
- package/src/teamix-evo-design-opentrek/patterns/dashboard.md +31 -0
- package/src/teamix-evo-design-opentrek/patterns/detail-page.md +202 -0
- package/src/teamix-evo-design-opentrek/patterns/form-page.md +289 -0
- package/src/teamix-evo-design-opentrek/patterns/list-page.md +334 -0
- package/src/teamix-evo-design-opentrek/patterns/page-types.md +154 -0
- package/src/teamix-evo-design-opentrek/philosophy.md +96 -0
- package/src/teamix-evo-design-opentrek/rules/README.md +39 -0
- package/src/teamix-evo-design-opentrek/rules/boundaries.rules.json +391 -0
- package/src/teamix-evo-design-uni-manager/SKILL.md +73 -0
- package/src/teamix-evo-design-uni-manager/boundaries.md +564 -0
- package/src/teamix-evo-design-uni-manager/brand.md +202 -0
- package/src/teamix-evo-design-uni-manager/checklist.md +115 -0
- package/src/teamix-evo-design-uni-manager/components.md +254 -0
- package/src/teamix-evo-design-uni-manager/flows.md +63 -0
- package/src/teamix-evo-design-uni-manager/foundations.md +258 -0
- package/src/teamix-evo-design-uni-manager/generation-flow.md +194 -0
- package/src/teamix-evo-design-uni-manager/patterns/dashboard.md +95 -0
- package/src/teamix-evo-design-uni-manager/patterns/detail-page.md +224 -0
- package/src/teamix-evo-design-uni-manager/patterns/form-page.md +329 -0
- package/src/teamix-evo-design-uni-manager/patterns/list-page.md +356 -0
- package/src/teamix-evo-design-uni-manager/patterns/page-types.md +165 -0
- package/src/teamix-evo-design-uni-manager/philosophy.md +106 -0
- package/src/teamix-evo-design-uni-manager/rules/README.md +49 -0
- package/src/teamix-evo-design-uni-manager/rules/boundaries.rules.json +418 -0
- package/src/teamix-evo-manage/SKILL.md +281 -0
- package/skills/teamix-evo-manage/SKILL.md +0 -138
package/README.md
CHANGED
|
@@ -39,14 +39,24 @@ pnpm --filter @teamix-evo/skills scaffold:skill
|
|
|
39
39
|
|
|
40
40
|
## 消费态命令(CLI)
|
|
41
41
|
|
|
42
|
-
由 `teamix-evo skills`
|
|
42
|
+
由 `teamix-evo skills` 子命令族管理(source-mirror 模型见 [ADR 0013](../../docs/adr/0013-skills-source-mirror.md)):
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
teamix-evo skills add
|
|
46
|
-
teamix-evo skills add <name
|
|
47
|
-
teamix-evo skills list
|
|
48
|
-
teamix-evo skills
|
|
49
|
-
teamix-evo skills
|
|
50
|
-
teamix-evo skills
|
|
51
|
-
teamix-evo skills uninstall
|
|
45
|
+
teamix-evo skills add # 全量装入 manifest 内所有 skill
|
|
46
|
+
teamix-evo skills add <name...> # 增量:仅装入指定 skill(可多个)
|
|
47
|
+
teamix-evo skills list # 列出全部 skill(默认:已装✓ / 未装○)
|
|
48
|
+
teamix-evo skills update # 升级到最新版(managed 策略保留你的自定义)
|
|
49
|
+
teamix-evo skills sync [name...] # 源 → IDE 镜像(漂移恢复用)
|
|
50
|
+
teamix-evo skills doctor # 检测源 / 镜像漂移
|
|
51
|
+
teamix-evo skills uninstall # 卸载(源 + 镜像 + lock)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 全局装机(`--scope global`)
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# 一行装到 ~/.qoder/skills/ 与 ~/.claude/skills/,元数据落到 ~/.teamix-evo-global/
|
|
58
|
+
npx teamix-evo@latest skills add teamix-evo-manage --scope global --ide claude,qoder -y
|
|
59
|
+
|
|
60
|
+
# 后续维护(update / uninstall 等)需 cd 到全局元数据根
|
|
61
|
+
cd ~/.teamix-evo-global && npx teamix-evo skills update
|
|
52
62
|
```
|
package/_template/SKILL.md.hbs
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: {{name}}
|
|
3
|
-
description:
|
|
3
|
+
description: |
|
|
4
|
+
{{description}}
|
|
5
|
+
TRIGGER when: <列举正向触发场景 / 短语 / 文件路径模式;3-8 条;具体优于抽象>
|
|
6
|
+
SKIP: <显式列出**不该**自己上的相邻情形,至少 2 条;指明该走哪个 skill>
|
|
7
|
+
Coordinates with: <可选;声明同时激活的 sibling skill>
|
|
4
8
|
---
|
|
5
9
|
|
|
6
10
|
# {{title}}
|
|
@@ -9,3 +13,12 @@ description: {{description}}
|
|
|
9
13
|
<!-- teamix-evo:managed:end id="core" -->
|
|
10
14
|
|
|
11
15
|
> 这部分内容由你(用户)自行编辑,CLI 升级时不会覆盖。
|
|
16
|
+
|
|
17
|
+
<!--
|
|
18
|
+
description 写法见 [ADR 0015](../../../docs/adr/0015-skill-description-trigger-contract.md):
|
|
19
|
+
- 第一行:一句话能力声明,≤ 100 字符,以动词开头
|
|
20
|
+
- TRIGGER when:正向枚举,具体优于抽象,中英文 + 文件 glob 三类信号都收
|
|
21
|
+
- SKIP:负向边界,**强制**字段,显式让位给相邻 skill
|
|
22
|
+
- Coordinates with:可选,声明协作而非抢活
|
|
23
|
+
manifest.json 的 description 必须与本字段完全一致(单源)。
|
|
24
|
+
-->
|
package/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://teamix-evo.dev/schema/skills-package/v1.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
4
|
"package": "skills",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.3.0",
|
|
6
6
|
"engines": {
|
|
7
7
|
"teamix-evo": ">=0.1.0"
|
|
8
8
|
},
|
|
@@ -10,12 +10,85 @@
|
|
|
10
10
|
{
|
|
11
11
|
"id": "teamix-evo-manage",
|
|
12
12
|
"name": "teamix-evo-manage",
|
|
13
|
-
"description": "
|
|
14
|
-
"version": "0.
|
|
15
|
-
"source": "
|
|
16
|
-
"ides": [
|
|
13
|
+
"description": "Single entry point for the teamix-evo lifecycle: scaffold a new project, install the AI coding system into an existing repo, run / update / inspect / remove any teamix-evo package, and drive the placeholder→real UI migration loop after `npm create teamix-evo`.\nTRIGGER when: (CLI) user runs or asks about `teamix-evo tokens ...` / `teamix-evo skills ...` / `teamix-evo ui ...` / `teamix-evo biz-ui ...` / `teamix-evo templates ...` / `teamix-evo logs ...`, or `npm create teamix-evo` / `pnpm create teamix-evo`; (模糊初始化) \"初始化一个项目\"、\"初始化一个工程\"、\"初始化一个 teamix-evo 工程\"、\"初始化一个 Teamix Evo 项目\"、\"create a teamix-evo project\"、\"set up teamix-evo from scratch\"、\"new teamix-evo app\"; (具名变体初始化) \"初始化一个 opentrek 工程 / op 工程 / OpenTrek 项目 / 探索者项目\"、\"初始化一个云管 / 云管控制台 / 云管项目 / uni-manager 工程 / 云管工程\"、\"new opentrek/uni-manager project\"; (AI coding 接入) \"给现有仓库装 teamix-evo\"、\"现有项目装一下 skills + ui\"、\"接入 AI coding 体系\"、\"装 teamix-evo 进这个项目\"、\"add teamix-evo to existing repo\"、\"install AI coding system\"、\"接入 opentrek 研发体系\"、\"接入 op 研发体系\"、\"接入 OpenTrek 研发体系\"、\"接入 opentrek 研发系统\"、\"接入 op 研发系统\"、\"接入云管研发体系\"、\"接入云管研发系统\"、\"接入 uni-manager 研发体系\"、\"接入 uni-manager 研发系统\"、\"接入统一管理研发体系\"; (更新检测) \"升级 teamix-evo\"、\"看看哪些要升级\"、\"update teamix-evo\"、\"check what needs updating\"、\"refresh installed teamix-evo packages\"; (卸载 / 清单) \"卸载 teamix-evo\"、\"看看装了哪些 teamix-evo 资源\"、\"remove the design system\"、\"list installed\"; (placeholder→real 升级) \"升级 UI\"、\"接入真组件\"、\"替换 placeholder\"、\"upgrade UI\"、\"replace placeholders\"、\"swap in real components\"、\"make the UI real\", or user opens / edits `src/components/_placeholder/**`, project contains `.teamix-evo/create/pending-ui.json`, literal `@teamix-evo:placeholder` tag in code; (状态文件) user touches `.teamix-evo/config.json`、`.teamix-evo/manifest.json`、`.teamix-evo/create/pending-ui.json`.\nSKIP: any content task — generating components, pages, services, or reviewing screens; changes to `src/` files outside the migration loop, design tokens, or business logic. Those go to teamix-evo-code-opentrek or teamix-evo-design-opentrek. SKIP if the user is mid-flow inside an already-initialized project asking to \"新增页面 / 加按钮 / 调接口\" — that's coding work, not lifecycle. SKIP pure styling / token tweaks — those go to ESLint + `tokens.overrides.css`.\nCoordinates with: teamix-evo-design-opentrek (visual side after a screen is generated)、teamix-evo-code-opentrek (file placement / reuse rules) — manage is the entry point and precedes content skills, never co-triggers.",
|
|
14
|
+
"version": "0.2.0",
|
|
15
|
+
"source": "src/teamix-evo-manage",
|
|
16
|
+
"ides": [
|
|
17
|
+
"qoder",
|
|
18
|
+
"claude"
|
|
19
|
+
],
|
|
17
20
|
"updateStrategy": "managed",
|
|
18
|
-
"managedRegions": [
|
|
21
|
+
"managedRegions": [
|
|
22
|
+
"core"
|
|
23
|
+
],
|
|
24
|
+
"template": false
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "teamix-evo-design-opentrek",
|
|
28
|
+
"name": "teamix-evo-design-opentrek",
|
|
29
|
+
"description": "Apply OpenTrek design system rules (philosophy, patterns, page-types, brand tone/voice, visual foundations) when AI generates or reviews a full UI screen / page in an OpenTrek-variant project.\nTRIGGER when: user asks to \"新建 / 优化 / 重构 一个页面\"、\"做一个列表页 / 详情页 / 表单页 / 仪表盘\"、\"create / review / refactor a page、screen、dashboard、template\"; intent involves layout structure, page-level information density, or multi-component composition; file write under `src/pages/**` or `src/templates/**`.\nSKIP: single-component edits like \"加个按钮\"、\"改 input 的 label\"; pure tokens/theme overrides; pure code refactor with no visual change; teamix-evo lifecycle commands (defer to teamix-evo-manage).\nCoordinates with: teamix-evo-code-opentrek (run alongside when the screen also creates new files).",
|
|
30
|
+
"version": "0.2.0",
|
|
31
|
+
"source": "src/teamix-evo-design-opentrek",
|
|
32
|
+
"variant": "opentrek",
|
|
33
|
+
"ides": [
|
|
34
|
+
"qoder",
|
|
35
|
+
"claude"
|
|
36
|
+
],
|
|
37
|
+
"updateStrategy": "managed",
|
|
38
|
+
"managedRegions": [
|
|
39
|
+
"core"
|
|
40
|
+
],
|
|
41
|
+
"template": false
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "teamix-evo-code-opentrek",
|
|
45
|
+
"name": "teamix-evo-code-opentrek",
|
|
46
|
+
"description": "Enforce teamix-evo coding conventions in OpenTrek-variant consumer apps — reuse-first against `@teamix-evo/ui` registry, API code under `src/services/`, `src/` layering and import boundaries.\nTRIGGER when: user asks to \"新增 / 重构 / 写一个\" 组件 / 页面 / 接口 / 钩子 / 工具 / hook; phrases like \"create a CRUD page\"、\"add an API call\"、\"extract a hook\"、\"refactor this fetch\"、\"调一下接口\"、\"加个组件\"、\"加个按钮\"; file write under `src/pages/**`、`src/components/**`、`src/services/**`、`src/hooks/**`; AI is about to write any new `.tsx` / `.ts` file in a teamix-evo-installed project.\nSKIP: pure visual / layout design questions about an already-existing screen with no code change (defer to teamix-evo-design-opentrek); teamix-evo lifecycle (init / update / uninstall) — those go to teamix-evo-manage; changes only to design tokens / styles / theme — those go to ESLint and `tokens.overrides.css`.\nCoordinates with: teamix-evo-design-opentrek (run alongside when the change also creates a UI screen — design handles the visual side, this skill handles file placement and reuse).",
|
|
47
|
+
"version": "0.2.0",
|
|
48
|
+
"source": "src/teamix-evo-code-opentrek",
|
|
49
|
+
"variant": "opentrek",
|
|
50
|
+
"ides": [
|
|
51
|
+
"qoder",
|
|
52
|
+
"claude"
|
|
53
|
+
],
|
|
54
|
+
"updateStrategy": "managed",
|
|
55
|
+
"managedRegions": [
|
|
56
|
+
"core"
|
|
57
|
+
],
|
|
58
|
+
"template": false
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "teamix-evo-design-uni-manager",
|
|
62
|
+
"name": "teamix-evo-design-uni-manager",
|
|
63
|
+
"description": "Apply Uni-Manager design system rules (philosophy, patterns, page-types, brand tone/voice, visual foundations) when AI generates or reviews a full UI screen / page in a Uni-Manager-variant project (专有云 / 混合云 / 云管平台 / hybrid cloud console).\nTRIGGER when: user asks to \"新建 / 优化 / 重构 一个页面\"、\"做一个列表页 / 详情页 / 表单页 / 仪表盘 / 控制台首页\"、\"create / review / refactor a page、screen、dashboard、console、admin template\"; intent involves layout structure, page-level information density, or multi-component composition for hybrid-cloud / multi-tenant / multi-region scenarios; file write under `src/pages/**` or `src/templates/**`.\nSKIP: single-component edits like \"加个按钮\"、\"改 input 的 label\"; pure tokens/theme overrides; pure code refactor with no visual change; teamix-evo lifecycle commands (defer to teamix-evo-manage).\nCoordinates with: teamix-evo-code-uni-manager (run alongside when the screen also creates new files).",
|
|
64
|
+
"version": "0.2.0",
|
|
65
|
+
"source": "src/teamix-evo-design-uni-manager",
|
|
66
|
+
"variant": "uni-manager",
|
|
67
|
+
"ides": [
|
|
68
|
+
"qoder",
|
|
69
|
+
"claude"
|
|
70
|
+
],
|
|
71
|
+
"updateStrategy": "managed",
|
|
72
|
+
"managedRegions": [
|
|
73
|
+
"core"
|
|
74
|
+
],
|
|
75
|
+
"template": false
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "teamix-evo-code-uni-manager",
|
|
79
|
+
"name": "teamix-evo-code-uni-manager",
|
|
80
|
+
"description": "Enforce teamix-evo coding conventions in uni-manager (hybrid-cloud / multi-tenant console) consumer apps — reuse-first against `@teamix-evo/ui` registry + `biz-ui/uni-manager` (um-topbar / CloudBadge), API code under `src/services/` with tenant / region context propagation, `src/` layering and import boundaries.\nTRIGGER when: user asks to \"新增 / 重构 / 写一个\" 组件 / 页面 / 接口 / 钩子 / 工具 / hook in a hybrid-cloud / 专有云 / 多租户 / 多区域 console; phrases like \"create a CRUD page\"、\"add an API call\"、\"extract a hook\"、\"refactor this fetch\"、\"调一下接口\"、\"加个组件\"、\"加个按钮\"; file write under `src/pages/**`、`src/components/**`、`src/services/**`、`src/hooks/**`; AI is about to write any new `.tsx` / `.ts` file in a teamix-evo-installed uni-manager-variant project.\nSKIP: pure visual / layout design questions about an already-existing screen with no code change (defer to teamix-evo-design-uni-manager); teamix-evo lifecycle (init / update / uninstall) — those go to teamix-evo-manage; changes only to design tokens / styles / theme — those go to ESLint and `tokens.overrides.css`.\nCoordinates with: teamix-evo-design-uni-manager (run alongside when the change also creates a UI screen — design handles the visual side, this skill handles file placement and reuse).",
|
|
81
|
+
"version": "0.2.0",
|
|
82
|
+
"source": "src/teamix-evo-code-uni-manager",
|
|
83
|
+
"variant": "uni-manager",
|
|
84
|
+
"ides": [
|
|
85
|
+
"qoder",
|
|
86
|
+
"claude"
|
|
87
|
+
],
|
|
88
|
+
"updateStrategy": "managed",
|
|
89
|
+
"managedRegions": [
|
|
90
|
+
"core"
|
|
91
|
+
],
|
|
19
92
|
"template": false
|
|
20
93
|
}
|
|
21
94
|
]
|
package/package.json
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamix-evo/skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Skills (AI IDE capabilities) for Teamix Evo",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"manifest.json",
|
|
8
8
|
"_data.json",
|
|
9
|
-
"
|
|
9
|
+
"src",
|
|
10
10
|
"_template"
|
|
11
11
|
],
|
|
12
12
|
"devDependencies": {
|
|
13
13
|
"@clack/prompts": "^0.8.0",
|
|
14
14
|
"tsx": "^4.0.0",
|
|
15
|
-
"@teamix-evo/registry": "0.
|
|
15
|
+
"@teamix-evo/registry": "0.3.0"
|
|
16
|
+
},
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public",
|
|
19
|
+
"registry": "https://registry.npmjs.org/"
|
|
16
20
|
},
|
|
17
21
|
"scripts": {
|
|
18
22
|
"validate": "tsx scripts/validate-skills.ts",
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: teamix-evo-code-opentrek
|
|
3
|
+
description: |
|
|
4
|
+
Enforce teamix-evo coding conventions in OpenTrek-variant consumer apps — reuse-first against `@teamix-evo/ui` registry, API code under `src/services/`, `src/` layering and import boundaries.
|
|
5
|
+
TRIGGER when: user asks to "新增 / 重构 / 写一个" 组件 / 页面 / 接口 / 钩子 / 工具 / hook; phrases like "create a CRUD page"、"add an API call"、"extract a hook"、"refactor this fetch"、"调一下接口"、"加个组件"、"加个按钮"; file write under `src/pages/**`、`src/components/**`、`src/services/**`、`src/hooks/**`; AI is about to write any new `.tsx` / `.ts` file in a teamix-evo-installed project.
|
|
6
|
+
SKIP: pure visual / layout design questions about an already-existing screen with no code change (defer to teamix-evo-design-opentrek); teamix-evo lifecycle (init / update / uninstall) — those go to teamix-evo-manage; changes only to design tokens / styles / theme — those go to ESLint and `tokens.overrides.css`.
|
|
7
|
+
Coordinates with: teamix-evo-design-opentrek (run alongside when the change also creates a UI screen — design handles the visual side, this skill handles file placement and reuse).
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# teamix-evo-code-opentrek
|
|
11
|
+
|
|
12
|
+
This skill bundles the **AI-readable engineering conventions** for OpenTrek-variant consumer business apps that consume `@teamix-evo/*` packages. It complements [`teamix-evo-design-opentrek`](../teamix-evo-design-opentrek/SKILL.md) — design tells AI _what a screen should look like_; this skill tells AI _where the code should live and what to reuse before writing new code_.
|
|
13
|
+
|
|
14
|
+
<!-- teamix-evo:managed:start id="core" -->
|
|
15
|
+
|
|
16
|
+
## When to use
|
|
17
|
+
|
|
18
|
+
Activate this skill whenever AI is about to **write or refactor code** inside a consumer app that has installed teamix-evo. Common signals:
|
|
19
|
+
|
|
20
|
+
- "新增一个 xxx 页面 / 列表页 / 详情页"
|
|
21
|
+
- "加一个 xxx 接口 / 调用 xxx API"
|
|
22
|
+
- "写一个 xxx 组件"
|
|
23
|
+
- "把这段重构一下"
|
|
24
|
+
- "create a CRUD page for orders"
|
|
25
|
+
- "add an API call to fetch users"
|
|
26
|
+
- Any time AI is about to create a new file under `src/pages/`、`src/components/`、`src/services/`、`src/hooks/`
|
|
27
|
+
|
|
28
|
+
If the task is purely about _visual design_ of a screen (layout / colors / spacing), use [`teamix-evo-design`](../teamix-evo-design/SKILL.md) instead — or run both in tandem.
|
|
29
|
+
|
|
30
|
+
## What this skill does
|
|
31
|
+
|
|
32
|
+
Before AI writes or commits code, it performs an **8-step gated flow**. Steps 1-4 are baseline (always run); steps 5-7 are topic gates (run when the task touches that topic); step 8 is the final self-review.
|
|
33
|
+
|
|
34
|
+
1. **Reuse-first check** — read [`reuse-first.md`](reuse-first.md). Before creating any new component, query the `@teamix-evo/ui` registry (via MCP `list_components` / `find_components`) and grep the local project. Only write new code when no reuse path exists.
|
|
35
|
+
2. **Layering check** — read [`api-layering.md`](api-layering.md). Any code that talks to a backend goes under `src/services/<domain>.ts`. Components never call `fetch` / `axios` directly. Data hooks live in `src/hooks/` and consume services.
|
|
36
|
+
3. **Directory check** — read [`file-structure.md`](file-structure.md). Place the new file under the right top-level folder (pages / components / services / hooks / types / utils / lib / stores / contexts). Each folder has a single responsibility and an import boundary.
|
|
37
|
+
4. **Forms gate** — if the task involves a form, read [`forms-and-validation.md`](forms-and-validation.md). `react-hook-form` + `zod`; schema lives at `src/services/<domain>.schema.ts`. Never wire forms with raw `useState`.
|
|
38
|
+
5. **Error/loading gate** — if the task adds a page or data hook, read [`error-and-loading.md`](error-and-loading.md). Ensure global ErrorBoundary, page-level fallback, and three-state handling (`isPending` / `isError` / data) are in place; mutations report success/error via `toast`.
|
|
39
|
+
6. **Routing gate** — if the task adds a route or page-entry, read [`routing-and-codesplit.md`](routing-and-codesplit.md). Pages use `React.lazy`; auth/role guards live in `src/routes/guards.tsx`; 404 / 403 / 500 fallbacks exist.
|
|
40
|
+
7. **Testing gate** — read [`testing.md`](testing.md). Pure functions and zod schemas are **mandatory** to test; hooks and reusable components are recommended. Test files sit next to the source as `*.test.ts(x)`; `vitest` + `@testing-library/react` + `msw`.
|
|
41
|
+
8. **Self-review** — run [`checklist.md`](checklist.md). Every item must pass before declaring the change done. Anything failing must be fixed or surfaced to the user.
|
|
42
|
+
|
|
43
|
+
## Inputs the user provides
|
|
44
|
+
|
|
45
|
+
- Intent: "add a page", "add a service call", "refactor X", "extract a hook", etc.
|
|
46
|
+
- Optional: domain entity (`order`、`user`、`tenant`、`workflow`)
|
|
47
|
+
- Optional: existing file the change should land near
|
|
48
|
+
|
|
49
|
+
## Outputs
|
|
50
|
+
|
|
51
|
+
- Code placed under the conventional path (`src/pages/<id>/`、`src/services/<domain>.ts`、…)
|
|
52
|
+
- Reuse decisions explicitly logged ("reused `Button` from `@teamix-evo/ui`" / "no match found, wrote a new `OrderCard` under `src/components/`")
|
|
53
|
+
- Pass / fail status against [`checklist.md`](checklist.md)
|
|
54
|
+
|
|
55
|
+
## How to invoke (typical flow)
|
|
56
|
+
|
|
57
|
+
1. Parse user intent → identify which artifact is being created (page / component / service / hook / util / form / route)
|
|
58
|
+
2. Read [`reuse-first.md`](reuse-first.md) and run the reuse query (MCP first, then local grep)
|
|
59
|
+
3. Read [`file-structure.md`](file-structure.md) to pick the destination directory
|
|
60
|
+
4. If the change touches network / backend, read [`api-layering.md`](api-layering.md)
|
|
61
|
+
5. If the change involves a form, read [`forms-and-validation.md`](forms-and-validation.md)
|
|
62
|
+
6. If the change adds a page / data hook, read [`error-and-loading.md`](error-and-loading.md) for fallback / Skeleton / toast wiring
|
|
63
|
+
7. If the change adds a route or page entry, read [`routing-and-codesplit.md`](routing-and-codesplit.md)
|
|
64
|
+
8. Decide test coverage per [`testing.md`](testing.md); write `*.test.ts(x)` next to source
|
|
65
|
+
9. Write the code; cite each reuse / new-write decision in the response
|
|
66
|
+
10. Run through [`checklist.md`](checklist.md); list pass / fail explicitly
|
|
67
|
+
|
|
68
|
+
## Files in this skill
|
|
69
|
+
|
|
70
|
+
| File | Purpose |
|
|
71
|
+
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
|
|
72
|
+
| [`reuse-first.md`](reuse-first.md) | Decision flow for reusing existing components / utilities before writing new ones |
|
|
73
|
+
| [`file-structure.md`](file-structure.md) | Top-level `src/` folder layout、ownership、import boundaries、naming、global-state tier (useState → Context → store) |
|
|
74
|
+
| [`api-layering.md`](api-layering.md) | Where API code lives (`src/services/`)、how data flows from service → hook → component |
|
|
75
|
+
| [`forms-and-validation.md`](forms-and-validation.md) | `react-hook-form` + `zod` patterns、schema location、submit/error wiring |
|
|
76
|
+
| [`error-and-loading.md`](error-and-loading.md) | Global / page ErrorBoundary、react-query three-state、Suspense、toast、reportError |
|
|
77
|
+
| [`routing-and-codesplit.md`](routing-and-codesplit.md) | `React.lazy` per page、guards、404/403/500 fallback、search-params state、Suspense placement |
|
|
78
|
+
| [`testing.md`](testing.md) | `vitest` + RTL + msw、co-located tests、what is mandatory vs recommended |
|
|
79
|
+
| [`checklist.md`](checklist.md) | Multi-section self-review before declaring done |
|
|
80
|
+
|
|
81
|
+
## Relationship to other skills
|
|
82
|
+
|
|
83
|
+
- [`teamix-evo-design-opentrek`](../teamix-evo-design-opentrek/SKILL.md) — visual / interaction rules for screen generation. Run **alongside** this skill when the task includes UI; this skill never overrides design on visual concerns.
|
|
84
|
+
- [`teamix-evo-manage`](../teamix-evo-manage/SKILL.md) — lifecycle (`init` / `update` / `uninstall` / `skills add`). Out of scope here.
|
|
85
|
+
|
|
86
|
+
## Why these conventions
|
|
87
|
+
|
|
88
|
+
- **Single source for UI** — `@teamix-evo/ui` is a source-injected component library (89 entries). Re-implementing `Button`、`Dialog`、`DataTable` etc. inside the consumer app fragments the design system and breaks token discipline.
|
|
89
|
+
- **Stable seams for change** — keeping API calls in `src/services/` means a backend rename only edits one file; keeping components free of fetch logic means they stay easy to test and reuse.
|
|
90
|
+
- **Predictable file location** — when AI (or a new teammate) opens an unfamiliar consumer app, the directory shape is the same across all teamix-evo-bootstrapped projects.
|
|
91
|
+
|
|
92
|
+
<!-- teamix-evo:managed:end -->
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# API 数据层规范
|
|
2
|
+
|
|
3
|
+
> **核心原则**:组件不直接 fetch。所有与后端通信的代码都落在 `src/services/`,通过 `src/hooks/` 暴露给组件。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 三层结构
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
┌────────────────────────────────────┐
|
|
11
|
+
│ src/pages/, src/components/ │ 组件层:消费 hook,渲染 UI
|
|
12
|
+
│ - 不调用 fetch / axios │
|
|
13
|
+
│ - 不直接读 process.env │
|
|
14
|
+
│ - 不拼 URL │
|
|
15
|
+
└──────────────┬─────────────────────┘
|
|
16
|
+
│ 仅通过 hook
|
|
17
|
+
▼
|
|
18
|
+
┌────────────────────────────────────┐
|
|
19
|
+
│ src/hooks/use<Domain>*.ts │ Hook 层:状态管理 + 缓存(react-query 等)
|
|
20
|
+
│ - 包装请求生命周期(loading/error) │
|
|
21
|
+
│ - 处理缓存 / 重试 / 失效 │
|
|
22
|
+
│ - 不写具体的 URL / payload 拼装 │
|
|
23
|
+
└──────────────┬─────────────────────┘
|
|
24
|
+
│ 调用纯函数
|
|
25
|
+
▼
|
|
26
|
+
┌────────────────────────────────────┐
|
|
27
|
+
│ src/services/<domain>.ts │ Service 层:请求纯函数
|
|
28
|
+
│ - 输入参数 → 输出 Promise<T> │
|
|
29
|
+
│ - 拼 URL / 序列化 / 反序列化 │
|
|
30
|
+
│ - 不依赖 React │
|
|
31
|
+
└──────────────┬─────────────────────┘
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
┌────────────────────────────────────┐
|
|
35
|
+
│ src/lib/http.ts │ 传输层:axios / fetch wrapper
|
|
36
|
+
│ - 鉴权 / baseURL / 错误归一化 │
|
|
37
|
+
│ - 全局 interceptor │
|
|
38
|
+
└────────────────────────────────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## §1 · `src/services/` 约定
|
|
44
|
+
|
|
45
|
+
### 文件组织
|
|
46
|
+
|
|
47
|
+
按**领域**(domain)拆,**不**按 HTTP 动词拆。
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
src/services/
|
|
51
|
+
├── order.ts # 订单领域:list / get / create / update / cancel
|
|
52
|
+
├── user.ts # 用户领域
|
|
53
|
+
├── tenant.ts # 租户领域
|
|
54
|
+
└── index.ts # 统一 re-export(可选)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
❌ 不要按动词拆:`getOrders.ts` / `createOrder.ts` / `updateOrder.ts` —— 会爆文件数。
|
|
58
|
+
|
|
59
|
+
### 函数签名约定
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
// src/services/order.ts
|
|
63
|
+
import { http } from '@/lib/http';
|
|
64
|
+
import type { Order, OrderListParams, CreateOrderInput } from '@/types/order';
|
|
65
|
+
|
|
66
|
+
export async function listOrders(params: OrderListParams): Promise<Order[]> {
|
|
67
|
+
const { data } = await http.get('/api/orders', { params });
|
|
68
|
+
return data.list;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function getOrder(id: string): Promise<Order> {
|
|
72
|
+
const { data } = await http.get(`/api/orders/${id}`);
|
|
73
|
+
return data;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export async function createOrder(input: CreateOrderInput): Promise<Order> {
|
|
77
|
+
const { data } = await http.post('/api/orders', input);
|
|
78
|
+
return data;
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
要点:
|
|
83
|
+
- **纯函数**(不依赖 React 上下文,可以在 SSR / Node 测试中单独跑)
|
|
84
|
+
- **类型来自 `src/types/`**,不要在 service 文件里就地定义 domain 类型
|
|
85
|
+
- **错误不在 service 层处理** —— 抛出去给 hook / 全局 interceptor 处理(归一化在 `src/lib/http.ts`)
|
|
86
|
+
- **不写 console.log / 业务弹窗** —— 是数据通道,不是 UI 通道
|
|
87
|
+
|
|
88
|
+
### 反模式
|
|
89
|
+
|
|
90
|
+
- ❌ `fetch('https://api.example.com/...')` 写死 host(应该用 `http` wrapper)
|
|
91
|
+
- ❌ service 函数返回 `{ loading, data, error }`(那是 hook 该做的)
|
|
92
|
+
- ❌ 在 service 里 `import { toast } from 'sonner'` 弹通知(归到 hook 或全局 interceptor)
|
|
93
|
+
- ❌ 一个 service 函数同时拼 URL、做业务计算、改全局 store
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## §2 · `src/hooks/` 约定
|
|
98
|
+
|
|
99
|
+
### 命名
|
|
100
|
+
|
|
101
|
+
- Query 类:`useOrderList`、`useOrder(id)`、`useUserProfile`
|
|
102
|
+
- Mutation 类:`useCreateOrder`、`useCancelOrder`、`useUpdateUser`
|
|
103
|
+
|
|
104
|
+
### 实现(以 `@tanstack/react-query` 为例)
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
// src/hooks/useOrderList.ts
|
|
108
|
+
import { useQuery } from '@tanstack/react-query';
|
|
109
|
+
import { listOrders } from '@/services/order';
|
|
110
|
+
import type { OrderListParams } from '@/types/order';
|
|
111
|
+
|
|
112
|
+
export function useOrderList(params: OrderListParams) {
|
|
113
|
+
return useQuery({
|
|
114
|
+
queryKey: ['orders', params],
|
|
115
|
+
queryFn: () => listOrders(params),
|
|
116
|
+
staleTime: 30_000,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
// src/hooks/useCreateOrder.ts
|
|
123
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
124
|
+
import { createOrder } from '@/services/order';
|
|
125
|
+
|
|
126
|
+
export function useCreateOrder() {
|
|
127
|
+
const qc = useQueryClient();
|
|
128
|
+
return useMutation({
|
|
129
|
+
mutationFn: createOrder,
|
|
130
|
+
onSuccess: () => qc.invalidateQueries({ queryKey: ['orders'] }),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 反模式
|
|
136
|
+
|
|
137
|
+
- ❌ Hook 里再次拼 URL(违反"service 拼 URL"边界)
|
|
138
|
+
- ❌ 一个 hook 调多个 service 把数据缝合 —— 缝合应该在 service 层(返回组合好的 DTO)
|
|
139
|
+
- ❌ Hook 里写业务跳转 / 路由切换 —— 由组件接 `mutation.onSuccess` callback 处理
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## §3 · `src/lib/http.ts` 约定
|
|
144
|
+
|
|
145
|
+
**全局只能有一份 http 实例**。提供:
|
|
146
|
+
|
|
147
|
+
- `baseURL`(从 env)
|
|
148
|
+
- 鉴权 header 注入
|
|
149
|
+
- 错误归一化(把后端 `{ code, message }` 变成 `Error` 抛出)
|
|
150
|
+
- 请求 ID / trace header
|
|
151
|
+
- (可选)mock 拦截
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
// src/lib/http.ts
|
|
155
|
+
import axios from 'axios';
|
|
156
|
+
|
|
157
|
+
export const http = axios.create({
|
|
158
|
+
baseURL: import.meta.env.VITE_API_BASE,
|
|
159
|
+
timeout: 15_000,
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
http.interceptors.request.use((config) => {
|
|
163
|
+
const token = localStorage.getItem('token');
|
|
164
|
+
if (token) config.headers.Authorization = `Bearer ${token}`;
|
|
165
|
+
return config;
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
http.interceptors.response.use(
|
|
169
|
+
(res) => res,
|
|
170
|
+
(err) => {
|
|
171
|
+
const message = err.response?.data?.message ?? err.message;
|
|
172
|
+
return Promise.reject(new Error(message));
|
|
173
|
+
},
|
|
174
|
+
);
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 反模式
|
|
178
|
+
|
|
179
|
+
- ❌ 在 service 里再 `import axios` 直接用(应该用 `http`)
|
|
180
|
+
- ❌ 多份 `http` 实例(分包拆 fetch 应该用一个 instance + 不同 baseURL config)
|
|
181
|
+
- ❌ 把鉴权放在每个 service 里手动加 header
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## §4 · 类型分层
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
src/types/
|
|
189
|
+
├── order.ts # Order、OrderStatus、OrderListParams、CreateOrderInput
|
|
190
|
+
├── user.ts
|
|
191
|
+
└── api.ts # 通用 ApiResponse<T>、Pagination<T>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
- **Domain 类型**(如 `Order`)放 `src/types/<domain>.ts`,被 service / hook / component 共享
|
|
195
|
+
- **API 入参 / 出参类型**:与 domain 类型分开命名(`OrderListParams` vs `Order`)
|
|
196
|
+
- **不要**让组件 props 类型直接 `import` service 的内部类型 —— 走 `src/types/` 中转
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## §5 · 何时可以打破
|
|
201
|
+
|
|
202
|
+
某些场景**允许**绕过本规范,但需要在代码注释里说明原因:
|
|
203
|
+
|
|
204
|
+
| 场景 | 允许 |
|
|
205
|
+
| --- | --- |
|
|
206
|
+
| 静态资源 fetch(读 `public/` 下的 json) | 组件直接 `fetch` 可,不用进 service |
|
|
207
|
+
| 第三方 SDK(地图、支付)有自己的客户端 | 包装层放 `src/lib/<sdk>.ts`,不强制走 services |
|
|
208
|
+
| 一次性的诊断 / 调试代码 | 临时 fetch 可,但 PR 合并前必须清理或归位 |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## AI 必须输出的层级日志
|
|
213
|
+
|
|
214
|
+
完成涉及网络 / 后端的改动时,AI 必须在响应里写明:
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
## 数据层改动
|
|
218
|
+
|
|
219
|
+
- src/types/order.ts: 新增 `OrderListParams`、`OrderStatus`
|
|
220
|
+
- src/services/order.ts: 新增 `listOrders`、`cancelOrder`(纯函数,使用 `@/lib/http`)
|
|
221
|
+
- src/hooks/useOrderList.ts: 包 `useQuery`,key=['orders', params]
|
|
222
|
+
- src/pages/orders/index.tsx: 仅消费 `useOrderList`,不直接 fetch
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
每一层都点到名,才算合规。
|