jsharness 1.10.0 → 1.12.2
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/.harness/README.md +1 -1
- package/.harness/agents/agent-dispatcher.md +66 -349
- package/.harness/agents/gate-controller/contract.yaml +1 -1
- package/.harness/agents/gate-controller/prompt.md +1 -1
- package/.harness/agents/gate-controller.md +1 -1
- package/.harness/agents/project-manager/contract.yaml +1 -1
- package/.harness/agents/project-manager/prompt.md +4 -1
- package/.harness/agents/project-manager.md +1 -1
- package/.harness/agents/requirements-analyst/contract.yaml +1 -1
- package/.harness/agents/requirements-analyst/prompt.md +2 -1
- package/.harness/agents/requirements-analyst.md +1 -1
- package/.harness/agents/solution-designer/contract.yaml +1 -1
- package/.harness/agents/solution-designer/prompt.md +1 -1
- package/.harness/agents/solution-designer.md +1 -1
- package/.harness/commands/js/deliver.md +43 -0
- package/.harness/commands/js/explore.md +18 -5
- package/.harness/commands/js/propose.md +4 -4
- package/.harness/doc/originRequirements/origin-main/.gitkeep +0 -0
- package/.harness/doc/prd/.gitkeep +0 -0
- package/.harness/doc/prd/prd-main/.gitkeep +0 -0
- package/.harness/doc/prd/prd-main/README.md +33 -0
- package/.harness/doc/team-guidelines/pm-team.md +1 -1
- package/.harness/doc/ttspec/.gitkeep +0 -0
- package/.harness/doc/ttspec/README.md +3 -3
- package/.harness/rules/project/frontend-coding-basics.md +519 -0
- package/.harness/skills/design-context-reader/SKILL.md +80 -0
- package/.harness/skills/docker-build/SKILL.md +1 -1
- package/.harness/skills/jsspec-deliver/SKILL.md +134 -0
- package/.harness/skills/{openspec-explore → jsspec-explore}/SKILL.md +35 -13
- package/.harness/skills/{openspec-propose → jsspec-propose}/SKILL.md +31 -16
- package/.harness/skills/{openspec-skill-creator → jsspec-skill-creator}/SKILL.md +17 -17
- package/.harness/workflow/definition.yaml +4 -4
- package/.harness/workflow/validate.js +1 -1
- package/files/front-coding-rules.md +665 -0
- package/lib/index.mjs +147 -20
- package/package.json +1 -1
- package/.harness/commands/js/apply.md +0 -31
- package/.harness/commands/js/archive.md +0 -31
- package/.harness/skills/openspec-apply/SKILL.md +0 -90
- package/.harness/skills/openspec-archive/SKILL.md +0 -77
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-coding-basics
|
|
3
|
+
description: 通用前端基础编码规范 — CSS 编码规范(BEM/属性顺序/选择器/声明块/数值/字体/z-index)+ JS/TS 基础语法规范(对象/数组/字符串/函数/箭头函数/Switch/ES6/TypeScript)+ 模块化开发规范 + 通用禁止事项
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
enabled: true
|
|
6
|
+
globs:
|
|
7
|
+
- "src/**/*.{ts,tsx,js,jsx,vue,css,scss,less}"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 通用前端基础编码规范 (frontend-coding-basics)
|
|
11
|
+
|
|
12
|
+
> **级别**: 项目级强制 | **适用范围**: 所有前端项目(框架无关)
|
|
13
|
+
> **来源**: `files/front-coding-rules.md` (v1.0.0) | **归档日期**: 2026-05-25
|
|
14
|
+
> **定位**: 填补全局编码规范(`coding-standard.md`)与 Vue3 专属规范(`frontend-vue3.md`)之间的通用前端基础层
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 引用说明
|
|
19
|
+
|
|
20
|
+
本文件与以下规则文件互补,重叠部分不重复写入:
|
|
21
|
+
|
|
22
|
+
| 已覆盖内容 | 规则文件 | 章节 |
|
|
23
|
+
|-----------|---------|------|
|
|
24
|
+
| 命名约定(camelCase/UPPER_SNAKE/PascalCase/BEM/handle 前缀/is 前缀) | `coding-standard.md` | §2 命名约定 |
|
|
25
|
+
| 注释规范(JSDoc、文件级注释、注释要点) | `coding-standard.md` | §5 注释规范 |
|
|
26
|
+
| 导入顺序(第三方库 → 项目内部 → 相邻模块 → 类型导入) | `coding-standard.md` | §3.3 导入顺序 |
|
|
27
|
+
| Vue3 组件规范(Composition API、defineProps、Pinia) | `frontend-vue3.md` | 全文 |
|
|
28
|
+
| Element Plus 组件使用规范 | `frontend-vue3.md` | §5 |
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 一、CSS 编码规范
|
|
33
|
+
|
|
34
|
+
### 1.1 BEM 命名规范
|
|
35
|
+
|
|
36
|
+
class 命名使用 BEM(Block、Element、Modifier),使用 `__` 与 `--` 连接:
|
|
37
|
+
|
|
38
|
+
```css
|
|
39
|
+
.block {} /* 块 */
|
|
40
|
+
.block__element {} /* 元素 */
|
|
41
|
+
.block--modifier {} /* 修饰符 */
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**为什么使用 BEM?** CSS 引擎查找样式表按从右到左顺序匹配,BEM 可减少嵌套层级,提升性能。
|
|
45
|
+
|
|
46
|
+
```css
|
|
47
|
+
/* ❌ 错误:深层嵌套 */
|
|
48
|
+
.main .content .title .name { color: #fff; }
|
|
49
|
+
|
|
50
|
+
/* ✅ 正确:BEM 扁平化 */
|
|
51
|
+
.content-title__name { color: #fff; }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 1.2 样式属性顺序
|
|
55
|
+
|
|
56
|
+
按照以下顺序书写属性:
|
|
57
|
+
|
|
58
|
+
1. **布局位置**(position, top, right, z-index, display, float 等)
|
|
59
|
+
2. **尺寸大小**(width, height, padding, margin)
|
|
60
|
+
3. **文字系列**(font, line-height, letter-spacing, color, text-align 等)
|
|
61
|
+
4. **视觉效果**(background, border 等)
|
|
62
|
+
5. **其他**(animation, transform 等)
|
|
63
|
+
|
|
64
|
+
```css
|
|
65
|
+
/* ❌ 错误:属性顺序混乱 */
|
|
66
|
+
.header {
|
|
67
|
+
background: #CCC;
|
|
68
|
+
font-size: 20px;
|
|
69
|
+
height: 50px;
|
|
70
|
+
border: 1px solid #bbb;
|
|
71
|
+
position: absolute;
|
|
72
|
+
left: 0;
|
|
73
|
+
top: 0;
|
|
74
|
+
width: 100%;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* ✅ 正确:按 布局→尺寸→文字→视觉→其他 排列 */
|
|
78
|
+
.header {
|
|
79
|
+
position: absolute;
|
|
80
|
+
left: 0;
|
|
81
|
+
top: 0;
|
|
82
|
+
width: 100%;
|
|
83
|
+
height: 50px;
|
|
84
|
+
font-size: 20px;
|
|
85
|
+
color: #f94000;
|
|
86
|
+
background: #CCC;
|
|
87
|
+
border: 1px solid #bbb;
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 1.3 选择器规范
|
|
92
|
+
|
|
93
|
+
| 规则 | 要求 | 违规后果 |
|
|
94
|
+
|------|------|----------|
|
|
95
|
+
| 嵌套层级 | 不大于 **3 级** | Code Review FAIL |
|
|
96
|
+
| ID 选择器 | 避免使用 | Code Review WARNING |
|
|
97
|
+
| 全局标签选择器 | 禁止使用(如 `div {}`, `button {}`) | Code Review FAIL |
|
|
98
|
+
| 标签名选择器 | CSS 选择器中避免使用标签名 | Code Review WARNING |
|
|
99
|
+
| @import | 尽量不要使用(与 `<link>` 相比速度较慢) | Code Review WARNING |
|
|
100
|
+
|
|
101
|
+
```css
|
|
102
|
+
/* ❌ 错误:全局标签选择器 */
|
|
103
|
+
div { padding-bottom: 0; }
|
|
104
|
+
button { border: 1px solid #ccc; }
|
|
105
|
+
|
|
106
|
+
/* ✅ 正确:使用类名选择器 */
|
|
107
|
+
.header { padding-bottom: 0; }
|
|
108
|
+
.custom-form { margin: 20px; }
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 1.4 规则声明块格式规范
|
|
112
|
+
|
|
113
|
+
1. 每条样式独占一行
|
|
114
|
+
2. 列表属性用逗号分隔,逗号后必须跟空格
|
|
115
|
+
3. 选择器与左大括号 `{` 之间必须加空格
|
|
116
|
+
4. 属性名与冒号之间不允许包含空格,冒号与属性值之间必须包含空格
|
|
117
|
+
5. 每条样式以分号 `;` 结尾
|
|
118
|
+
6. 右大括号 `}` 独占一行
|
|
119
|
+
7. 每个规则声明间用空行分隔
|
|
120
|
+
|
|
121
|
+
```css
|
|
122
|
+
/* ✅ 正确 */
|
|
123
|
+
.selector {
|
|
124
|
+
position: absolute;
|
|
125
|
+
width: 100%;
|
|
126
|
+
font-family: 'Helvetica', 'Arial', sans-serif;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.another-selector {
|
|
130
|
+
margin: 0;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 1.5 数值与长度规范
|
|
135
|
+
|
|
136
|
+
| 规则 | 要求 | 示例 |
|
|
137
|
+
|------|------|------|
|
|
138
|
+
| 0-1 小数 | 省略整数部分的 0 | `opacity: .8` 非 `0.8` |
|
|
139
|
+
| 长度为 0 | 省略单位 | `padding: 0 5px` 非 `0px 5px` |
|
|
140
|
+
| 颜色值 | 使用缩写格式 | `#f40` 非 `#ff4400` |
|
|
141
|
+
| 命名色值 | 禁止使用 | 禁止 `lightgreen`,用 `#90ee90` |
|
|
142
|
+
|
|
143
|
+
```css
|
|
144
|
+
/* ✅ 正确 */
|
|
145
|
+
.panel { opacity: .8; }
|
|
146
|
+
.list { padding: 0 5px; }
|
|
147
|
+
.header { color: #f40; }
|
|
148
|
+
|
|
149
|
+
/* ❌ 错误:命名色值 */
|
|
150
|
+
.button--success { color: lightgreen; }
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 1.6 字体排版规范
|
|
154
|
+
|
|
155
|
+
| 规则 | 要求 | 原因 |
|
|
156
|
+
|------|------|------|
|
|
157
|
+
| 字号 | 不小于 **12px** | Windows 平台中文显示限制 |
|
|
158
|
+
| font-weight | 使用数值方式 | `700` 而非 `bold`,精确控制 |
|
|
159
|
+
| line-height | 使用数值而非像素值 | 浏览器基于 font-size 自动计算 |
|
|
160
|
+
|
|
161
|
+
```css
|
|
162
|
+
/* ❌ 错误 */
|
|
163
|
+
.title { font-weight: bold; }
|
|
164
|
+
.container { line-height: 15px; }
|
|
165
|
+
|
|
166
|
+
/* ✅ 正确 */
|
|
167
|
+
.title { font-weight: 700; }
|
|
168
|
+
.container { line-height: 1.5; }
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### 1.7 其他 CSS 规范
|
|
172
|
+
|
|
173
|
+
| 规则 | 要求 |
|
|
174
|
+
|------|------|
|
|
175
|
+
| !important | 除公共样式外,业务代码中尽量不使用 |
|
|
176
|
+
| z-index | 建议分层管理(如:dropdown 100、modal 200、toast 300) |
|
|
177
|
+
| Media Query | 不得单独编排,须与相关规则一起定义 |
|
|
178
|
+
| CSS 变量 | 集中配置在全局变量中,方便统一管理 |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 二、JavaScript / TypeScript 基础语法规范
|
|
183
|
+
|
|
184
|
+
> **命名约定**(camelCase/UPPER_SNAKE/handle 前缀/is 前缀)见 `coding-standard.md` §2。
|
|
185
|
+
> **注释规范**(JSDoc、文件级注释、注释要点)见 `coding-standard.md` §5。
|
|
186
|
+
|
|
187
|
+
### 2.1 对象规范
|
|
188
|
+
|
|
189
|
+
#### 2.1.1 使用字面量创建对象
|
|
190
|
+
|
|
191
|
+
```javascript
|
|
192
|
+
// ❌ 错误
|
|
193
|
+
const obj = new Object()
|
|
194
|
+
|
|
195
|
+
// ✅ 正确
|
|
196
|
+
const obj = {}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### 2.1.2 对象属性简写
|
|
200
|
+
|
|
201
|
+
属性名与变量名一致时必须使用简写:
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
const job = 'FrontEnd'
|
|
205
|
+
|
|
206
|
+
// ❌ 错误
|
|
207
|
+
const item = { job: job }
|
|
208
|
+
|
|
209
|
+
// ✅ 正确
|
|
210
|
+
const item = { job }
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### 2.1.3 对象拷贝 — 优先使用展开运算符
|
|
214
|
+
|
|
215
|
+
```javascript
|
|
216
|
+
// ❌ 错误
|
|
217
|
+
const copy = Object.assign({}, original, { c: 3 })
|
|
218
|
+
|
|
219
|
+
// ✅ 正确
|
|
220
|
+
const copy = { ...original, c: 3 }
|
|
221
|
+
const { a, ...noA } = copy // noA => { b: 2, c: 3 }
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
#### 2.1.4 非法标识符引号
|
|
225
|
+
|
|
226
|
+
只对非法标识符的属性使用引号:
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
// ❌ 错误
|
|
230
|
+
const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5 }
|
|
231
|
+
|
|
232
|
+
// ✅ 正确
|
|
233
|
+
const good = { foo: 3, bar: 4, 'data-blah': 5 }
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
#### 2.1.5 属性访问
|
|
237
|
+
|
|
238
|
+
使用 `.` 来访问对象属性(动态键除外):
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
const joke = { name: 'haha', age: 28 }
|
|
242
|
+
|
|
243
|
+
// ❌ 错误
|
|
244
|
+
const name = joke['name']
|
|
245
|
+
|
|
246
|
+
// ✅ 正确
|
|
247
|
+
const name = joke.name
|
|
248
|
+
|
|
249
|
+
// ✅ 正确:动态键
|
|
250
|
+
const key = 'name'
|
|
251
|
+
const val = joke[key]
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### 2.2 数组规范
|
|
255
|
+
|
|
256
|
+
| 场景 | 要求 | 违规后果 |
|
|
257
|
+
|------|------|----------|
|
|
258
|
+
| 创建数组 | 使用字面量 `[]` | Code Review WARNING |
|
|
259
|
+
| 添加元素 | 使用 `push` | Code Review WARNING |
|
|
260
|
+
| 复制数组 | 使用展开运算符 `[...arr]` | Code Review WARNING |
|
|
261
|
+
| 类数组转数组 | 使用 `Array.from` | Code Review WARNING |
|
|
262
|
+
| 取值 | 使用数组解构赋值 | Code Review WARNING |
|
|
263
|
+
| map 方法 | 必须有 return | Code Review FAIL |
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
// ❌ 错误
|
|
267
|
+
const items = new Array()
|
|
268
|
+
items[items.length] = 'test'
|
|
269
|
+
const copy = arr.slice()
|
|
270
|
+
|
|
271
|
+
// ✅ 正确
|
|
272
|
+
const items = []
|
|
273
|
+
items.push('test')
|
|
274
|
+
const copy = [...items]
|
|
275
|
+
const arrLike = { 0: 'foo', 1: 'bar', length: 2 }
|
|
276
|
+
const arr = Array.from(arrLike)
|
|
277
|
+
const [first, second] = arr
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### 2.3 字符串规范
|
|
281
|
+
|
|
282
|
+
| 规则 | 要求 | 示例 |
|
|
283
|
+
|------|------|------|
|
|
284
|
+
| 定义 | 统一使用单引号 | `'JDC'` 非 `"JDC"` |
|
|
285
|
+
| 动态生成 | 使用模板字符串 | `` `ab${test}` `` 非 `'a' + 'b' + test` |
|
|
286
|
+
| eval | 禁止使用 | 存在安全漏洞 |
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
// ❌ 错误
|
|
290
|
+
const department = "JDC"
|
|
291
|
+
const str = 'a' + 'b' + test
|
|
292
|
+
|
|
293
|
+
// ✅ 正确
|
|
294
|
+
const department = 'JDC'
|
|
295
|
+
const str = `ab${test}`
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### 2.4 函数规范
|
|
299
|
+
|
|
300
|
+
| 规则 | 要求 | 违规后果 |
|
|
301
|
+
|------|------|----------|
|
|
302
|
+
| 函数签名 | 函数签名与函数体之间有空格 | Code Review WARNING |
|
|
303
|
+
| Function 构造函数 | 禁止使用 `new Function()` | Code Review FAIL |
|
|
304
|
+
| 块中声明函数 | 禁止在非函数代码块中声明函数 | Code Review FAIL |
|
|
305
|
+
| arguments | 禁止使用,改用剩余参数 `...args` | Code Review FAIL |
|
|
306
|
+
| 参数默认值 | 使用参数默认值语法 | Code Review WARNING |
|
|
307
|
+
| 默认值位置 | 有默认值的参数放在最后 | Code Review WARNING |
|
|
308
|
+
| 参数重新赋值 | 禁止对参数重新赋值 | Code Review FAIL |
|
|
309
|
+
|
|
310
|
+
```javascript
|
|
311
|
+
// ❌ 错误
|
|
312
|
+
const add = new Function('a', 'b', 'return a + b')
|
|
313
|
+
if (isUse) { function test() {} }
|
|
314
|
+
function test() { const args = Array.prototype.slice.call(arguments) }
|
|
315
|
+
function handleThings(opts) { opts = opts || {} }
|
|
316
|
+
function handleThings(opts = {}, name) {}
|
|
317
|
+
const foo = function(bar) { bar = 13 }
|
|
318
|
+
|
|
319
|
+
// ✅ 正确
|
|
320
|
+
const add = (a, b) => a + b
|
|
321
|
+
let test
|
|
322
|
+
if (isUse) { test = () => {} }
|
|
323
|
+
function test(...args) { return args.join('') }
|
|
324
|
+
function handleThings(opts = {}) {}
|
|
325
|
+
function handleThings(name, opts = {}) {}
|
|
326
|
+
const foo = function(bar) { let baz = bar }
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### 2.5 箭头函数规范
|
|
330
|
+
|
|
331
|
+
| 规则 | 要求 |
|
|
332
|
+
|------|------|
|
|
333
|
+
| 匿名函数 | 传递匿名函数时优先使用箭头函数 |
|
|
334
|
+
| 单表达式 | 函数体只包含一条无副作用的返回表达式 → 省略花括号,隐式 return |
|
|
335
|
+
| 多语句 | 保留花括号并使用 return |
|
|
336
|
+
| 返回对象 | 返回对象字面量必须加括号 |
|
|
337
|
+
|
|
338
|
+
```javascript
|
|
339
|
+
// ✅ 正确:单一表达式
|
|
340
|
+
[1, 2, 3].map(number => `A string containing the ${number}.`)
|
|
341
|
+
|
|
342
|
+
// ✅ 正确:多行语句
|
|
343
|
+
[1, 2, 3].map((number) => {
|
|
344
|
+
const nextNumber = number + 1
|
|
345
|
+
return `A string containing the ${nextNumber}.`
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
// ✅ 正确:返回对象需加括号
|
|
349
|
+
[1, 2, 3].map((number, index) => ({ index: number }))
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### 2.6 Switch 规范
|
|
353
|
+
|
|
354
|
+
- 每个 case 必须做好防穿透处理(break)
|
|
355
|
+
- 最后必须有 default 默认出口
|
|
356
|
+
|
|
357
|
+
```javascript
|
|
358
|
+
// ❌ 错误:case 2 缺少 break,缺少 default
|
|
359
|
+
switch (foo) {
|
|
360
|
+
case 1:
|
|
361
|
+
bar()
|
|
362
|
+
break
|
|
363
|
+
case 2:
|
|
364
|
+
quux()
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// ✅ 正确
|
|
368
|
+
switch (foo) {
|
|
369
|
+
case 1:
|
|
370
|
+
bar()
|
|
371
|
+
break
|
|
372
|
+
case 2:
|
|
373
|
+
quux()
|
|
374
|
+
break
|
|
375
|
+
default:
|
|
376
|
+
baz()
|
|
377
|
+
break
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### 2.7 ES6 语法优先
|
|
382
|
+
|
|
383
|
+
| 场景 | ES6 写法 | 替代的 ES5 模式 |
|
|
384
|
+
|------|---------|---------------|
|
|
385
|
+
| 匿名函数 | 箭头函数 | `function() {}` |
|
|
386
|
+
| 异步操作 | async/await | 回调地狱 |
|
|
387
|
+
| 取值 | 解构赋值 | `const x = obj.x` |
|
|
388
|
+
| 变量声明 | const 优先(必要时 let,**禁止 var**) | `var` |
|
|
389
|
+
| 迭代 | for...of | 手动索引循环 |
|
|
390
|
+
| 拷贝合并 | 展开运算符 `...` | `Object.assign` / 手动循环 |
|
|
391
|
+
|
|
392
|
+
### 2.8 TypeScript 类型约束
|
|
393
|
+
|
|
394
|
+
> **基础 TS 类型安全**(禁止裸 any、Props 使用 interface)见 `coding-standard.md` §1 和 `frontend-vue3.md` §2。
|
|
395
|
+
|
|
396
|
+
| 规则 | 要求 | 违规后果 |
|
|
397
|
+
|------|------|----------|
|
|
398
|
+
| 禁止滥用 any | 不确定类型时使用 `unknown` 而非 `any` | Code Review WARNING |
|
|
399
|
+
| interface vs type | interface 用于描述对象结构,type 用于联合类型/工具类型 | Code Review WARNING |
|
|
400
|
+
| 公共 API 类型 | 入参/出参必须显式声明类型 | Code Review FAIL |
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
// ❌ 错误
|
|
404
|
+
function process(data: any): any { return data }
|
|
405
|
+
|
|
406
|
+
// ✅ 正确
|
|
407
|
+
interface UserData { id: string; name: string }
|
|
408
|
+
function process(data: UserData): UserData { return data }
|
|
409
|
+
|
|
410
|
+
// ✅ interface 用于对象结构
|
|
411
|
+
interface UserProps { id: string; name: string }
|
|
412
|
+
|
|
413
|
+
// ✅ type 用于联合类型/工具类型
|
|
414
|
+
type Status = 'active' | 'inactive'
|
|
415
|
+
type Nullable<T> = T | null
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## 三、模块化开发规范
|
|
421
|
+
|
|
422
|
+
> **导入顺序**(第三方库 → 项目内部 → 相邻模块 → 类型导入)见 `coding-standard.md` §3.3。
|
|
423
|
+
|
|
424
|
+
### 3.1 使用标准 ES6 模块语法
|
|
425
|
+
|
|
426
|
+
```javascript
|
|
427
|
+
// ❌ 错误
|
|
428
|
+
const util = require('./util')
|
|
429
|
+
module.exports = util
|
|
430
|
+
|
|
431
|
+
// ✅ 正确
|
|
432
|
+
import Util from './util'
|
|
433
|
+
export default Util
|
|
434
|
+
|
|
435
|
+
// ✅ 更好:具名导出
|
|
436
|
+
import { Util } from './util'
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### 3.2 同个文件每个模块只 import 一次
|
|
440
|
+
|
|
441
|
+
```javascript
|
|
442
|
+
// ❌ 错误
|
|
443
|
+
import foo from 'foo'
|
|
444
|
+
// ... 其他 imports ...
|
|
445
|
+
import { named1, named2 } from 'foo'
|
|
446
|
+
|
|
447
|
+
// ✅ 正确
|
|
448
|
+
import foo, { named1, named2 } from 'foo'
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### 3.3 禁止 import 后再添加 import
|
|
452
|
+
|
|
453
|
+
import 语句必须置于文件顶部,业务代码之后不得再插入 import:
|
|
454
|
+
|
|
455
|
+
```javascript
|
|
456
|
+
// ❌ 错误
|
|
457
|
+
import foo from 'foo'
|
|
458
|
+
foo.init()
|
|
459
|
+
import bar from 'bar'
|
|
460
|
+
|
|
461
|
+
// ✅ 正确
|
|
462
|
+
import foo from 'foo'
|
|
463
|
+
import bar from 'bar'
|
|
464
|
+
|
|
465
|
+
foo.init()
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### 3.4 多行导入格式
|
|
469
|
+
|
|
470
|
+
多行导入像多行数组和对象一样缩进:
|
|
471
|
+
|
|
472
|
+
```javascript
|
|
473
|
+
// ❌ 错误
|
|
474
|
+
import { longNameA, longNameB, longNameC, longNameD, longNameE } from 'path'
|
|
475
|
+
|
|
476
|
+
// ✅ 正确
|
|
477
|
+
import {
|
|
478
|
+
longNameA,
|
|
479
|
+
longNameB,
|
|
480
|
+
longNameC,
|
|
481
|
+
longNameD,
|
|
482
|
+
longNameE
|
|
483
|
+
} from 'path'
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### 3.5 禁止在 import 声明中使用 Webpack loader 语法
|
|
487
|
+
|
|
488
|
+
```javascript
|
|
489
|
+
// ❌ 错误
|
|
490
|
+
import fooSass from 'css!sass!foo.scss'
|
|
491
|
+
|
|
492
|
+
// ✅ 正确
|
|
493
|
+
import fooSass from 'foo.scss'
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
## 四、通用禁止事项清单(MUST NOT)
|
|
499
|
+
|
|
500
|
+
> 以下仅列出与 `coding-standard.md` 和 `frontend-vue3.md` **不重复**的禁止事项。重复条目见对应文件。
|
|
501
|
+
|
|
502
|
+
| 编号 | 禁止事项 | 说明 | 违规后果 |
|
|
503
|
+
|------|---------|------|----------|
|
|
504
|
+
| CB-01 | 禁止使用 `eval()` | 存在安全漏洞 | Code Review FAIL |
|
|
505
|
+
| CB-02 | 禁止 CSS 嵌套 > 3 层 | 使用 BEM 命名扁平化 | Code Review FAIL |
|
|
506
|
+
| CB-03 | 禁止全局标签选择器修改样式 | 使用类名选择器 | Code Review FAIL |
|
|
507
|
+
| CB-04 | 禁止在非函数块中声明函数 | 改用变量赋值箭头函数 | Code Review FAIL |
|
|
508
|
+
| CB-05 | 禁止使用 `arguments` | 使用剩余参数 `...args` | Code Review FAIL |
|
|
509
|
+
| CB-06 | 禁止重复 import 同一模块 | 合并为单条 import 语句 | Code Review WARNING |
|
|
510
|
+
| CB-07 | 禁止 Switch 缺少 default 分支 | 必须包含 default 默认出口 | Code Review FAIL |
|
|
511
|
+
| CB-08 | 禁止 import 后再添加 import | import 语句必须置于文件顶部 | Code Review WARNING |
|
|
512
|
+
| CB-09 | 禁止使用 `new Object()` / `new Array()` | 使用字面量 `{}` / `[]` | Code Review WARNING |
|
|
513
|
+
| CB-10 | 禁止使用双引号定义字符串 | 统一使用单引号,动态字符串使用模板字符串 | Code Review WARNING |
|
|
514
|
+
|
|
515
|
+
> **与现有规则的对应关系**:
|
|
516
|
+
> - C001(禁止 any)→ `coding-standard.md` §1 已覆盖
|
|
517
|
+
> - C009(禁止 var)→ `coding-standard.md` §3.4 已覆盖
|
|
518
|
+
> - C010(禁止双引号)→ 本表 CB-10
|
|
519
|
+
> - FV-01~FV-07 → `frontend-vue3.md` §8 已覆盖
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design-context-reader
|
|
3
|
+
description: 研发设计上下文读取技能 — 根据任务编号自动加载需求阶段的 PRD 和 ttspec change 内容,作为架构设计/研发设计的强制前置步骤
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
enabled: true
|
|
6
|
+
outputPath: .harness/doc/
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 研发设计上下文读取技能 (design-context-reader)
|
|
10
|
+
|
|
11
|
+
> **Skill 类型**: 开发设计辅助 Skill
|
|
12
|
+
> **触发场景**: 架构设计或研发设计阶段开始前,作为强制前置步骤
|
|
13
|
+
> **所属 Agent**: architect / developer
|
|
14
|
+
> **作用**: 根据任务编号自动加载 PRD 和 ttspec change 内容
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 1. 核心职责
|
|
19
|
+
|
|
20
|
+
作为研发设计上下文读取技能,核心职责是:
|
|
21
|
+
|
|
22
|
+
1. **根据任务编号关联并读取 PRD 文档**
|
|
23
|
+
2. **根据任务编号关联并读取 ttspec change 内容**
|
|
24
|
+
3. **作为架构/研发设计的强制前置步骤**
|
|
25
|
+
|
|
26
|
+
### 1.1 触发条件
|
|
27
|
+
|
|
28
|
+
以下场景**必须**先执行本 Skill 读取上下文:
|
|
29
|
+
|
|
30
|
+
- 执行架构设计(使用 `architecture-designer` Skill)
|
|
31
|
+
- 执行研发设计(编写设计文档)
|
|
32
|
+
- 执行代码审查时需要理解业务上下文
|
|
33
|
+
|
|
34
|
+
### 1.2 输入
|
|
35
|
+
|
|
36
|
+
| 输入项 | 来源 | 格式 | 必须 |
|
|
37
|
+
|--------|------|------|------|
|
|
38
|
+
| 任务编号 / change 名称 | tasks.md 或用户指定 | 字符串 | 是 |
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 2. 执行步骤
|
|
43
|
+
|
|
44
|
+
### Step 1: 读取 PRD 文档
|
|
45
|
+
|
|
46
|
+
按以下顺序查找 PRD 文件:
|
|
47
|
+
|
|
48
|
+
1. **暂存区查找**:`.harness/doc/prd/requirements-{name}.md`
|
|
49
|
+
- 如果找到 → 读取并显示 "已加载 PRD:requirements-{name}.md"
|
|
50
|
+
2. **归档区查找**:`.harness/doc/prd/prd-main/{module}/requirements-{name}.md`
|
|
51
|
+
- 遍历 prd-main/ 下所有模块子目录查找匹配文件
|
|
52
|
+
- 如果找到 → 读取并显示 "已加载 PRD(已归档):prd-main/{module}/requirements-{name}.md"
|
|
53
|
+
3. **未找到** → 记录 "未找到关联 PRD,基于 ttspec change 内容进行设计"
|
|
54
|
+
|
|
55
|
+
### Step 2: 读取 ttspec change 内容
|
|
56
|
+
|
|
57
|
+
按以下顺序查找 change 目录:
|
|
58
|
+
|
|
59
|
+
1. **活跃区查找**:`.harness/doc/ttspec/change/{name}/`
|
|
60
|
+
- 如果找到 → 读取 proposal.md、design.md、specs/、tasks.md
|
|
61
|
+
- 显示 "已加载 change:{name}(活跃)"
|
|
62
|
+
2. **归档区查找**:`.harness/doc/ttspec/change/archive/{date}-{name}/`
|
|
63
|
+
- 遍历 archive/ 下查找匹配目录
|
|
64
|
+
- 如果找到 → 读取相关文件并显示 "已加载 change:{name}(已归档)"
|
|
65
|
+
3. **未找到** → 警告 "未找到 ttspec change 目录,设计可能缺少上下文"
|
|
66
|
+
|
|
67
|
+
### Step 3: 上下文就绪确认
|
|
68
|
+
|
|
69
|
+
- 如果 PRD 和 ttspec change 均未找到 → 警告用户但允许继续
|
|
70
|
+
- 如果至少找到一个 → 在设计过程中引用已加载的上下文
|
|
71
|
+
- 在设计产出中**必须**引用来源(PRD 文件路径或 change 目录路径)
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 3. 约束
|
|
76
|
+
|
|
77
|
+
- **强制前置** — 设计任务开始前必须先执行本 Skill,未读取上下文禁止开始设计
|
|
78
|
+
- **不阻塞** — 即使 PRD 和 ttspec change 都未找到,仅警告不阻断
|
|
79
|
+
- **引用来源** — 设计产出中必须标注上下文来源
|
|
80
|
+
- **所有输出使用中文**
|