@mingfuyun/star-allinone 0.1.7 → 0.1.9

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
@@ -12,6 +12,117 @@ yarn add @mingfuyun/star-allinone
12
12
  pnpm add @mingfuyun/star-allinone
13
13
  ```
14
14
 
15
+ ## Skill 如何使用
16
+
17
+ 公共 skill 由本仓库维护,随 `@mingfuyun/star-allinone` 发布。业务项目用 CLI 同步到自己的 `.agents/skills/shared-*` 并提交。Codex / Cursor 直接从业务仓库发现 skill,不写入 `~/.codex/skills`,团队成员也不需要本仓库源码。
18
+
19
+ ```text
20
+ .agents/skills/
21
+ ├── shared-* ← npm 包同步,不能在业务项目直接改
22
+ └── custom-* ← 业务项目自己维护
23
+ ```
24
+
25
+ 完整约定见 [skills/README.md](skills/README.md)。
26
+
27
+ ### 命令
28
+
29
+ 全部在**业务项目根目录**执行:
30
+
31
+ ```bash
32
+ pnpm exec star-allinone skills list
33
+ pnpm exec star-allinone skills sync --dry-run
34
+ pnpm exec star-allinone skills sync
35
+ ```
36
+
37
+ `list` 查看包内公共 skill。`sync` 把它们写入当前项目的 `.agents/skills/shared-*`,会整体替换过期的 `shared-*`,但不会改 `custom-*`。
38
+
39
+ ### 维护者:改公共 skill
40
+
41
+ 1. 修改 `skills/shared/<name>/SKILL.md`,例如 `skills/shared/api-to-service/SKILL.md`
42
+ 2. 发布新版本 `@mingfuyun/star-allinone`
43
+ 3. 业务项目升级依赖并重新同步(见下方)
44
+
45
+ 不要把流水线 ID 或 OpenAPI 快照写进 `skills/shared`。流水线 ID 放在业务项目 `.star-allinone.json` 的 `publishPipelineId`。审查、提交、发布、Mock 和 Service 生成都是公共 skill。
46
+
47
+ ### 业务项目:首次接入
48
+
49
+ 1. 安装依赖:
50
+
51
+ ```bash
52
+ pnpm add @mingfuyun/star-allinone
53
+ ```
54
+
55
+ 2. 在项目根目录添加 `.star-allinone.json`:
56
+
57
+ ```json
58
+ {
59
+ "project": "starscope-frontend",
60
+ "publicSkillPrefix": "shared-",
61
+ "serviceDir": "src/services",
62
+ "openapi": ".agents/project/openapi.json",
63
+ "publishPipelineId": "5108336"
64
+ }
65
+ ```
66
+
67
+ StarLink 示例见 `examples/projects/`。
68
+
69
+ 3. 同步公共 skill:
70
+
71
+ ```bash
72
+ pnpm exec star-allinone skills sync
73
+ ```
74
+
75
+ 4. 把真正的业务特例放到 `.agents/skills/custom-*`。审查、提交、发布、Mock 和 Service 生成不要做成 `custom-*`。
76
+
77
+ 5. 提交配置和 skill:
78
+
79
+ ```bash
80
+ git add .star-allinone.json .agents/skills
81
+ git commit -m "chore(skill): 接入公共 skill"
82
+ ```
83
+
84
+ ### 业务项目:日常调用
85
+
86
+ 在 Codex / Cursor 对话里用 `$skill-name` 显式调用,例如:
87
+
88
+ ```text
89
+ 使用 $shared-api-to-service,为 GET /api/v1/devices/ 生成类型、Service 和 JSON Mock。
90
+ ```
91
+
92
+ ```text
93
+ 使用 $shared-design-to-page,根据我上传的设计稿生成页面。
94
+ 缺少的 Service、类型和 Mock 一并生成。
95
+ ```
96
+
97
+ ```text
98
+ 使用 $shared-review-and-submit,对当前变更执行提交前审查。
99
+ 等我确认后再提交。
100
+ ```
101
+
102
+ ```text
103
+ 使用 $shared-publish-test,把当前分支发布到测试环境。
104
+ ```
105
+
106
+ 公共流程用 `shared-*`,项目专属规则用 `custom-*`。业务定制 skill 需要复用公共流程时,在 `custom-*` 的 `SKILL.md` 里写明先读取对应的 `.agents/skills/shared-*/SKILL.md`。
107
+
108
+ ### 业务项目:更新公共 skill
109
+
110
+ ```bash
111
+ pnpm update @mingfuyun/star-allinone
112
+ pnpm exec star-allinone skills sync
113
+ git add package.json pnpm-lock.yaml .agents/skills/shared-*
114
+ git commit -m "chore(skill): 更新公共 skill"
115
+ ```
116
+
117
+ 其他成员只需:
118
+
119
+ ```bash
120
+ git pull
121
+ pnpm install
122
+ ```
123
+
124
+ 不要手动修改 `shared-*`。下次 `skills sync` 会覆盖这些目录。
125
+
15
126
  ### 在 Umi 项目中使用
16
127
 
17
128
  如果您的项目使用 **Umi** 框架,组件库会自动从您的项目中获取 `@umijs/max` 的能力(如 `useAccess`)。
@@ -593,4 +704,3 @@ MIT License
593
704
  ---
594
705
 
595
706
  Made with ❤️ by 星系运维团队
596
-
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@mingfuyun/star-allinone",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "星系运维前端能力包",
5
5
  "main": "dist/index.js",
6
+ "bin": {
7
+ "star-allinone": "scripts/cli.js"
8
+ },
6
9
  "types": "dist/index.d.ts",
7
10
  "style": "dist/index.css",
8
11
  "exports": {
@@ -25,12 +28,16 @@
25
28
  },
26
29
  "files": [
27
30
  "dist",
28
- "README.md"
31
+ "README.md",
32
+ "scripts/cli.js",
33
+ "skills"
29
34
  ],
30
35
  "scripts": {
31
36
  "build": "webpack --env format=umd --mode=none && webpack --env format=esm --mode=none",
32
37
  "publish": "node scripts/publish.js",
33
38
  "publish:dev": "node scripts/publish.js --dev",
39
+ "skills:sync": "node scripts/cli.js skills sync",
40
+ "skills:list": "node scripts/cli.js skills list",
34
41
  "prepublishOnly": "npm run build",
35
42
  "test": "echo \"Error: no test specified\" && exit 1",
36
43
  "dev": "webpack --mode=none --watch",
package/scripts/cli.js ADDED
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const path = require('path');
6
+
7
+ const root = path.resolve(__dirname, '..');
8
+ const skillsRoot = path.join(root, 'skills', 'shared');
9
+ const DEFAULT_PREFIX = 'shared-';
10
+ const CUSTOM_PREFIX = 'custom-';
11
+
12
+ function readJson(file) {
13
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
14
+ }
15
+
16
+ function usage() {
17
+ console.log(`Usage:
18
+ star-allinone skills list
19
+ star-allinone skills sync [--target <dir>] [--dry-run]
20
+
21
+ Run the command from a business project containing .star-allinone.json.
22
+
23
+ Sync writes package skills/shared/* to <project>/.agents/skills/shared-*.
24
+ It never writes ~/.codex/skills and never modifies custom-* skills.`);
25
+ process.exitCode = 1;
26
+ }
27
+
28
+ function listSharedSkillNames() {
29
+ if (!fs.existsSync(skillsRoot)) return [];
30
+ return fs.readdirSync(skillsRoot, { withFileTypes: true })
31
+ .filter((entry) => entry.isDirectory())
32
+ .map((entry) => entry.name)
33
+ .sort();
34
+ }
35
+
36
+ function listSkills() {
37
+ const skills = listSharedSkillNames();
38
+ if (!skills.length) {
39
+ console.log('No shared skills found.');
40
+ return;
41
+ }
42
+ for (const name of skills) {
43
+ console.log(`${name} -> ${DEFAULT_PREFIX}${name}`);
44
+ }
45
+ }
46
+
47
+ function parseArgs(args) {
48
+ const options = { dryRun: false };
49
+ const positional = [];
50
+ for (let index = 0; index < args.length; index += 1) {
51
+ const arg = args[index];
52
+ if (arg === '--dry-run') options.dryRun = true;
53
+ else if (arg === '--target') options.target = args[++index];
54
+ else positional.push(arg);
55
+ }
56
+ return { options, positional };
57
+ }
58
+
59
+ function render(content, variables) {
60
+ return content.replace(/\{\{\s*([\w.-]+)\s*\}\}/g, (_, key) => {
61
+ const value = key.split('.').reduce((current, part) => current?.[part], variables);
62
+ if (value === undefined || value === null) {
63
+ throw new Error(`Missing template variable: ${key}`);
64
+ }
65
+ return String(value);
66
+ });
67
+ }
68
+
69
+ function publicSkillName(skillName, prefix) {
70
+ return `${prefix}${skillName}`;
71
+ }
72
+
73
+ function assertSafeDestination(destination) {
74
+ const normalized = path.resolve(destination);
75
+ const codexSkills = path.resolve(os.homedir(), '.codex', 'skills');
76
+ if (normalized === codexSkills || normalized.startsWith(`${codexSkills}${path.sep}`)) {
77
+ throw new Error('Refusing to write to ~/.codex/skills');
78
+ }
79
+ }
80
+
81
+ const TEMPLATE_EXT = new Set(['.md', '.json', '.yml', '.yaml', '.txt']);
82
+
83
+ function copyTree(source, target, variables, options, relativeRoot) {
84
+ for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
85
+ const sourcePath = path.join(source, entry.name);
86
+ const targetPath = path.join(target, entry.name);
87
+ if (entry.isDirectory()) {
88
+ if (!options.dryRun) fs.mkdirSync(targetPath, { recursive: true });
89
+ copyTree(sourcePath, targetPath, variables, options, relativeRoot);
90
+ continue;
91
+ }
92
+ const relativePath = path.relative(relativeRoot, targetPath);
93
+ console.log(`${options.dryRun ? '[dry-run] ' : ''}${relativePath}`);
94
+ if (options.dryRun) continue;
95
+ fs.mkdirSync(path.dirname(targetPath), { recursive: true });
96
+ const ext = path.extname(entry.name).toLowerCase();
97
+ if (TEMPLATE_EXT.has(ext)) {
98
+ fs.writeFileSync(targetPath, render(fs.readFileSync(sourcePath, 'utf8'), variables));
99
+ } else {
100
+ fs.copyFileSync(sourcePath, targetPath);
101
+ }
102
+ }
103
+ }
104
+
105
+ function copySkill(source, destination, skillName, prefix, variables, options) {
106
+ const publicName = publicSkillName(skillName, prefix);
107
+ if (publicName.startsWith(CUSTOM_PREFIX)) {
108
+ throw new Error(`Public skill prefix cannot be "${CUSTOM_PREFIX}"`);
109
+ }
110
+ const skillTarget = path.join(destination, publicName);
111
+ if (!options.dryRun) {
112
+ fs.rmSync(skillTarget, { recursive: true, force: true });
113
+ fs.mkdirSync(skillTarget, { recursive: true });
114
+ }
115
+ copyTree(source, skillTarget, { ...variables, sharedSkillName: publicName }, options, destination);
116
+ }
117
+
118
+ function pruneStaleShared(destination, prefix, syncedNames, options) {
119
+ if (!fs.existsSync(destination)) return;
120
+ for (const entry of fs.readdirSync(destination, { withFileTypes: true })) {
121
+ if (!entry.isDirectory()) continue;
122
+ if (entry.name.startsWith(CUSTOM_PREFIX)) continue;
123
+ if (!entry.name.startsWith(prefix)) continue;
124
+ if (syncedNames.includes(entry.name)) continue;
125
+ const relativePath = path.relative(destination, path.join(destination, entry.name));
126
+ console.log(`${options.dryRun ? '[dry-run] ' : ''}remove stale ${relativePath}`);
127
+ if (!options.dryRun) {
128
+ fs.rmSync(path.join(destination, entry.name), { recursive: true, force: true });
129
+ }
130
+ }
131
+ }
132
+
133
+ function selectedSharedSkills(config) {
134
+ const available = listSharedSkillNames();
135
+ if (!config.sharedSkills) return available;
136
+ const missing = config.sharedSkills.filter((name) => !available.includes(name));
137
+ if (missing.length) {
138
+ throw new Error(`Unknown sharedSkills: ${missing.join(', ')}`);
139
+ }
140
+ return available.filter((name) => config.sharedSkills.includes(name));
141
+ }
142
+
143
+ function syncProject(options) {
144
+ const target = path.resolve(options.target || process.cwd());
145
+ const configFile = path.join(target, '.star-allinone.json');
146
+ if (!fs.existsSync(configFile)) throw new Error(`Missing project config: ${configFile}`);
147
+ const config = readJson(configFile);
148
+ const prefix = config.publicSkillPrefix || DEFAULT_PREFIX;
149
+ const destination = path.join(target, '.agents', 'skills');
150
+ assertSafeDestination(destination);
151
+
152
+ const variables = { ...config, ...config.variables, project: { ...config, ...config.variables } };
153
+ const skills = selectedSharedSkills(config);
154
+ const syncedNames = skills.map((name) => publicSkillName(name, prefix));
155
+
156
+ if (!options.dryRun) fs.mkdirSync(destination, { recursive: true });
157
+ for (const skillName of skills) {
158
+ copySkill(path.join(skillsRoot, skillName), destination, skillName, prefix, variables, options);
159
+ }
160
+ pruneStaleShared(destination, prefix, syncedNames, options);
161
+ console.log(`${options.dryRun ? 'Would sync' : 'Synced'} shared skills -> ${destination}`);
162
+ }
163
+
164
+ function main() {
165
+ const [group, command, ...rest] = process.argv.slice(2);
166
+ if (group !== 'skills') return usage();
167
+ if (command === 'list') return listSkills();
168
+ if (command !== 'sync') return usage();
169
+ const { options, positional } = parseArgs(rest);
170
+ if (positional.length) return usage();
171
+ syncProject(options);
172
+ }
173
+
174
+ try {
175
+ main();
176
+ } catch (error) {
177
+ console.error(`Error: ${error.message}`);
178
+ process.exitCode = 1;
179
+ }
@@ -0,0 +1,297 @@
1
+ # Skills
2
+
3
+ 公共 skill 和业务定制 skill 都保存在业务项目仓库中,但通过目录命名和来源规则明确区分。
4
+
5
+ 不使用 Codex 全局目录 `~/.codex/skills`,也不要求团队成员拥有 `star-allinone` 源码。
6
+
7
+ ## 推荐目录
8
+
9
+ 以 `starscope-frontend` 为例:
10
+
11
+ ```text
12
+ starscope-frontend/
13
+ ├── .star-allinone.json
14
+ └── .agents/
15
+ ├── skills/
16
+ │ ├── shared-api-to-service/
17
+ │ ├── shared-api-mock/
18
+ │ ├── shared-design-to-page/
19
+ │ ├── shared-verify/
20
+ │ ├── shared-review-and-submit/
21
+ │ ├── shared-publish-test/
22
+ │ └── custom-device-management/
23
+ └── project/
24
+ ├── conventions.md
25
+ ├── review-rules.md
26
+ └── openapi.json
27
+ ```
28
+
29
+ StarLink:
30
+
31
+ ```text
32
+ starlink-frontend/
33
+ └── .agents/
34
+ └── skills/
35
+ ├── shared-api-to-service/
36
+ ├── shared-api-mock/
37
+ ├── shared-design-to-page/
38
+ ├── shared-verify/
39
+ ├── shared-review-and-submit/
40
+ ├── shared-publish-test/
41
+ └── custom-node-management/
42
+ ```
43
+
44
+ 命名约定:
45
+
46
+ ```text
47
+ shared-* 公共 skill,由 star-allinone 提供,经 CLI 同步后提交到业务仓库
48
+ custom-* 业务定制 skill,由业务项目维护
49
+ ```
50
+
51
+ 这样所有 skill 都在业务项目中,Codex 可以直接发现;同时通过名称可以清楚区分来源。
52
+
53
+ ## npm 包的职责
54
+
55
+ `@mingfuyun/star-allinone` 包中保存公共 skill 源文件。每个 skill 包含可执行规则,细节放在同目录 `references/`:
56
+
57
+ ```text
58
+ @mingfuyun/star-allinone/
59
+ └── skills/
60
+ └── shared/
61
+ ├── api-to-service/
62
+ │ ├── SKILL.md
63
+ │ └── references/
64
+ │ ├── service-conventions.md
65
+ │ └── api-artifact-generation.md
66
+ ├── api-mock/
67
+ ├── design-to-page/ # page-conventions.md + overlays.md
68
+ ├── project-conventions/ # architecture / review-checklist / quality-checklist
69
+ ├── verify/
70
+ ├── review-and-submit/
71
+ ├── impact-analysis/
72
+ ├── ai-review/
73
+ ├── commit-current-changes/
74
+ └── publish-test/ # 流水线 ID 从 .star-allinone.json 读取
75
+ ```
76
+
77
+ 公共 skill 写死两边已对齐的硬规则,例如:页面走 `MFRequest`、DTO 放 namespace typings、`MFProTable` + `ProForm`、弹层用 `BaseModal` / `CustomDrawer` / `HocModal`、`await` 必须 try/catch、禁止无说明的 `any`。
78
+
79
+ 业务项目的 `.agents/project/` 只写差异:路径、权限体系、OpenAPI 位置、领域特例。项目文件可以补充,但不能削弱公共硬规则。
80
+
81
+ CLI 只做同步:
82
+
83
+ ```text
84
+ npm 包中的 skills/shared
85
+ ↓
86
+ 业务项目 .agents/skills/shared-*
87
+ ```
88
+
89
+ 不会写入:
90
+
91
+ ```text
92
+ ~/.codex/skills
93
+ ```
94
+
95
+ 也不会管理业务项目的 `custom-*` skill。
96
+
97
+ ## CLI 使用方式
98
+
99
+ 在业务项目目录执行:
100
+
101
+ ```bash
102
+ pnpm exec star-allinone skills sync
103
+ ```
104
+
105
+ CLI 根据当前业务项目的 `.star-allinone.json`,直接将公共 skill 写入当前项目:
106
+
107
+ ```text
108
+ 当前项目/.agents/skills/shared-*/
109
+ ```
110
+
111
+ 例如:
112
+
113
+ ```bash
114
+ cd /path/to/starscope-frontend
115
+ pnpm exec star-allinone skills sync
116
+ ```
117
+
118
+ 结果:
119
+
120
+ ```text
121
+ .agents/skills/
122
+ ├── shared-api-to-service/
123
+ ├── shared-api-mock/
124
+ ├── shared-review-and-submit/
125
+ ├── shared-publish-test/
126
+ └── custom-*/
127
+ ```
128
+
129
+ 公共 skill 的更新不会影响业务定制 skill。同步会整体替换 `shared-*` 目录,并删除包中已不存在的过期 `shared-*`,但不会改动 `custom-*`。
130
+
131
+ ## 新增或修改公共 skill
132
+
133
+ 管理者操作:
134
+
135
+ ```text
136
+ 修改 star-allinone/skills/shared/api-to-service/SKILL.md
137
+ → 发布新版本 @mingfuyun/star-allinone
138
+ ```
139
+
140
+ 业务项目操作:
141
+
142
+ ```bash
143
+ pnpm update @mingfuyun/star-allinone
144
+ pnpm exec star-allinone skills sync
145
+ git add package.json pnpm-lock.yaml .agents/skills/shared-*
146
+ git commit -m "chore(skill): 更新公共 skill"
147
+ ```
148
+
149
+ 团队成员只需要:
150
+
151
+ ```bash
152
+ git pull
153
+ pnpm install
154
+ ```
155
+
156
+ 由于公共 skill 已经提交到业务仓库,所以团队成员不需要手动安装全局 skill,也不需要拥有 `star-allinone` 源码。
157
+
158
+ ## 新增或修改业务定制 skill
159
+
160
+ 业务项目直接维护:
161
+
162
+ ```text
163
+ .agents/skills/custom-device-management/SKILL.md
164
+ ```
165
+
166
+ 提交即可:
167
+
168
+ ```bash
169
+ git add .agents/skills/custom-device-management
170
+ git commit -m "feat(skill): 增加设备管理 skill"
171
+ ```
172
+
173
+ 不需要修改 `star-allinone`,也不需要重新发布 npm。
174
+
175
+ 审查、提交、测试环境发布、Mock 和 Service 生成都走公共 skill。只有流水线 ID 放在业务项目的 `.star-allinone.json`。`custom-*` 只用于真正的业务特例,例如设备管理或节点管理。
176
+
177
+ ## 公共部分和业务定制组合
178
+
179
+ 例如业务定制 skill 需要复用公共 API 生成流程:
180
+
181
+ ```text
182
+ .agents/skills/custom-device-service/SKILL.md
183
+ ```
184
+
185
+ 内容中引用公共 skill:
186
+
187
+ ```md
188
+ ---
189
+ name: custom-device-service
190
+ description: Generate StarScope device service code.
191
+ ---
192
+
193
+ 本任务需要结合公共 skill `shared-api-to-service` 执行。
194
+
195
+ 先读取并遵循:
196
+
197
+ `.agents/skills/shared-api-to-service/SKILL.md`
198
+
199
+ 再读取当前项目的:
200
+
201
+ - OpenAPI 文件
202
+ - Service 约定
203
+ - 项目类型和权限规则
204
+
205
+ 只生成符合当前项目结构的设备相关 service。
206
+ ```
207
+
208
+ 公共 skill 负责通用流程,业务 skill 负责具体业务规则。
209
+
210
+ ## 项目配置
211
+
212
+ 项目差异配置放在业务项目中,例如:
213
+
214
+ ```text
215
+ starscope-frontend/
216
+ ├── .star-allinone.json
217
+ └── .agents/
218
+ ├── skills/
219
+ └── project/
220
+ ├── conventions.md
221
+ ├── review-rules.md
222
+ └── openapi.json
223
+ ```
224
+
225
+ ```json
226
+ {
227
+ "project": "starscope-frontend",
228
+ "publicSkillPrefix": "shared-",
229
+ "serviceDir": "src/services",
230
+ "openapi": ".agents/project/openapi.json",
231
+ "publishPipelineId": "5108336"
232
+ }
233
+ ```
234
+
235
+ StarLink 使用:
236
+
237
+ ```json
238
+ {
239
+ "project": "starlink-frontend",
240
+ "publicSkillPrefix": "shared-",
241
+ "publishPipelineId": "5245265"
242
+ }
243
+ ```
244
+
245
+ 完整示例见 `examples/projects/`。
246
+
247
+ 可选字段 `sharedSkills` 用于只同步部分公共 skill;省略时同步 `skills/shared` 下的全部公共 skill。
248
+
249
+ ## 公共规则写在哪里
250
+
251
+ | Skill | 规则位置 | 覆盖内容 |
252
+ | --- | --- | --- |
253
+ | `shared-api-to-service` | SKILL + `references/service-conventions.md`、`api-artifact-generation.md` | 指定 operation、`MFRequest` 映射、namespace 类型、snake_case、schema 闭包、禁止改 transport |
254
+ | `shared-api-mock` | SKILL + `references/mock-conventions.md` | 对话 JSON 默认、完整响应信封、分页/空列表/错误场景、禁止 handler 和随机数 |
255
+ | `shared-design-to-page` | SKILL + `references/page-conventions.md`、`overlays.md` | 页面分层、`MFProTable`、`ProForm`、权限、异步、`HocModal` 弹层合同 |
256
+ | `shared-project-conventions` | SKILL + `references/architecture.md`、`review-checklist.md`、`quality-checklist.md` | 架构边界、质量禁令、审查清单;其他 skill 会引用这些文件 |
257
+ | `shared-verify` | SKILL | 成套产物检查、await/loading/弹层、验证命令和报告格式 |
258
+ | `shared-impact-analysis` | SKILL | 只读影响分类和回归路径 |
259
+ | `shared-ai-review` | SKILL | Hooks、契约、权限、性能、安全的 P0–P3 审查 |
260
+ | `shared-commit-current-changes` | SKILL | 确认门禁、中文 Conventional Commit、禁止未确认就提交 |
261
+ | `shared-review-and-submit` | SKILL | impact → verify → commit review 编排 |
262
+ | `shared-publish-test` | SKILL + `scripts/publish-current-branch.sh` | 云效测试流水线发布;只从配置读 `publishPipelineId`;git push 后不自动跑,需单独确认「推送流水线」 |
263
+
264
+ 以下内容**不**写进公共 skill 源码:
265
+
266
+ - 流水线 ID:放在业务项目 `.star-allinone.json` 的 `publishPipelineId`
267
+ - OpenAPI 快照:业务仓库数据文件,路径由 `.star-allinone.json` 的 `openapi` 指向
268
+ - 真正的业务特例:权限常量名、Clear Cache 登记、IP 校验、设备/节点领域规则,放 `custom-*`
269
+
270
+ ## 最终推荐流程
271
+
272
+ 公共 skill:
273
+
274
+ ```text
275
+ star-allinone 修改
276
+ → 发布 npm
277
+ → 业务项目升级 npm
278
+ → 执行 skills sync
279
+ → 提交 .agents/skills/shared-*
280
+ ```
281
+
282
+ 业务定制 skill:
283
+
284
+ ```text
285
+ 业务项目直接新增或修改 custom-*
286
+ → 提交业务项目
287
+ ```
288
+
289
+ 最终结构和责任边界:
290
+
291
+ ```text
292
+ .agents/skills/
293
+ ├── shared-* ← npm 包同步,不能在业务项目直接维护
294
+ └── custom-* ← 业务项目自己维护
295
+ ```
296
+
297
+ 这比全局安装更适合团队协作,也比把公共 skill 藏在 `node_modules` 中更可靠,因为公共 skill 最终会进入业务项目仓库,团队成员拉取代码后即可直接使用。
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: {{sharedSkillName}}
3
+ description: Review frontend changes for correctness, API and permission contracts, React lifecycle, performance, maintainability, security, accessibility, and test gaps. Use for a standalone review without commit. Do not modify files.
4
+ ---
5
+
6
+ # AI Code Review
7
+
8
+ This skill is fully shared. Review the current diff plus relevant callers and types. Before reviewing, read:
9
+
10
+ 1. `.agents/skills/shared-project-conventions/references/review-checklist.md`
11
+ 2. `.agents/skills/shared-project-conventions/references/quality-checklist.md`
12
+
13
+ Do not require a project-local review-rules file. If `.agents/project/review-rules.md` exists, apply extra domain checks only; do not weaken shared hard rules.
14
+
15
+ ## Required checks
16
+
17
+ 1. React Hooks: stale closures, incomplete dependencies, request races, updates after unmount, unnecessary rerenders.
18
+ 2. API contracts: method/path/params, response unwrapping, pagination, nullability, enum drift, error handling, DTO mismatch.
19
+ 3. Permissions: route access, button visibility, mutation authorization, client-only enforcement.
20
+ 4. Forms/tables: validation, reset, duplicate submit, refresh after mutation, column-state, long text, empty/error.
21
+ 5. Performance: eager `xlsx`/editor imports, duplicate libraries, large lists without virtualization, unstable columns/handlers, avoidable requests.
22
+ 6. Security/privacy: tokens, user data, URLs, unsafe HTML, sensitive logs, environment config.
23
+ 7. Tests and accessibility: critical paths, failure states, keyboard labels, disabled/loading semantics.
24
+
25
+ ## Output
26
+
27
+ Lead with findings ordered `[P0]`–`[P3]`, with file and line. Separate blocking issues from recommendations. Do not report style preferences as bugs.
28
+
29
+ If none, write `No issues found.` Always include validation performed and gaps. Do not modify files unless the user explicitly asks for fixes.
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: {{sharedSkillName}}
3
+ description: Generate deterministic API mock responses matching the active frontend project's OpenAPI contract and service types. Use when the user asks for JSON fixtures, proxy-ready mock data, empty or error scenarios, or mock files for a specified endpoint.
4
+ ---
5
+
6
+ # API Mock
7
+
8
+ This skill is fully shared. Read [references/mock-conventions.md](references/mock-conventions.md), `.star-allinone.json`, the related service types, and the OpenAPI file from `openapi` in `.star-allinone.json` (or the document provided in this conversation).
9
+
10
+ If the service contract is missing, first follow `.agents/skills/shared-api-to-service/SKILL.md`.
11
+
12
+ ## Hard rules
13
+
14
+ - OpenAPI and existing namespace types are authoritative. Do not invent undocumented fields.
15
+ - Default output is labeled conversation JSON. Write `mock/<api-path>/<method>.json` only when the user explicitly asks for files.
16
+ - Keep the complete backend envelope. Service callers see unwrapped `data`; mocks must not drop `code` / `message` / `data`.
17
+ - Preserve snake_case, required fields, enums, nullability, and pagination totals.
18
+ - Never add runtime handlers, `defineMock`, Faker, current timestamps, or unseeded randomness without an explicit request.
19
+ - Cover requested scenarios only. Success is the default; empty, overflow, zero, validation, and permission cases need an explicit ask or a documented contract.
20
+
21
+ ## Handoff
22
+
23
+ For every endpoint, report HTTP method, path, scenario label, and one strict parseable JSON block. If files were written, list the paths and confirm they parse as JSON.