jsharness 1.0.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/.harness/README.md +199 -0
- package/.harness/agents/code-reviewer/contract.yaml +64 -0
- package/.harness/agents/developer/contract.yaml +72 -0
- package/.harness/agents/gate-controller/contract.yaml +64 -0
- package/.harness/agents/project-manager/contract.yaml +77 -0
- package/.harness/agents/prompt-templates.md +352 -0
- package/.harness/agents/requirements-analyst/contract.yaml +64 -0
- package/.harness/agents/solution-designer/contract.yaml +75 -0
- package/.harness/agents/tester/contract.yaml +92 -0
- package/.harness/config/models.yaml +67 -0
- package/.harness/dev-map/backend/api-definition.md +131 -0
- package/.harness/dev-map/backend/auth-security.md +131 -0
- package/.harness/dev-map/backend/conventions-java.md +471 -0
- package/.harness/dev-map/backend/conventions.md +192 -0
- package/.harness/dev-map/backend/database.md +106 -0
- package/.harness/dev-map/backend/structure.md +140 -0
- package/.harness/dev-map/decisions.md +275 -0
- package/.harness/dev-map/frontend/api-integration.md +139 -0
- package/.harness/dev-map/frontend/components.md +178 -0
- package/.harness/dev-map/frontend/conventions.md +416 -0
- package/.harness/dev-map/frontend/state-management.md +170 -0
- package/.harness/dev-map/frontend/structure.md +103 -0
- package/.harness/dev-map/overview.md +267 -0
- package/.harness/docs/integration-test-plan.md +248 -0
- package/.harness/docs/team-guidelines/README.md +161 -0
- package/.harness/docs/team-guidelines/arch-team.md +811 -0
- package/.harness/docs/team-guidelines/collaboration.md +556 -0
- package/.harness/docs/team-guidelines/pm-team.md +337 -0
- package/.harness/docs/team-guidelines/qa-team.md +562 -0
- package/.harness/docs/team-guidelines/rd-team.md +714 -0
- package/.harness/docs/training-materials.md +280 -0
- package/.harness/gate/baseline.js +220 -0
- package/.harness/gate/checks/build-gates-frontend.js +152 -0
- package/.harness/gate/checks/build-gates-java.js +155 -0
- package/.harness/gate/checks/build-gates.js +119 -0
- package/.harness/gate/checks/engineering-consistency.js +138 -0
- package/.harness/gate/checks/security-quality.js +129 -0
- package/.harness/gate/checks/static-compliance.js +313 -0
- package/.harness/gate/checks/test-compliance.js +114 -0
- package/.harness/gate/index.js +315 -0
- package/.harness/mcp/config.yaml +435 -0
- package/.harness/rules/global/coding-standard.md +232 -0
- package/.harness/rules/global/commit-convention.md +165 -0
- package/.harness/rules/global/process-discipline.md +192 -0
- package/.harness/rules/global/security-baseline.md +306 -0
- package/.harness/rules/project/frontend-vue3.md +293 -0
- package/.harness/rules/project/java-backend.md +460 -0
- package/.harness/rules/project/web-specific.md +231 -0
- package/.harness/skills/build.md +192 -0
- package/.harness/skills/code-review.md +251 -0
- package/.harness/skills/docker-build.md +227 -0
- package/.harness/skills/docs-update.md +164 -0
- package/.harness/skills/java-build.md +261 -0
- package/.harness/skills/lint-check.md +482 -0
- package/.harness/skills/task-board-maintenance.md +105 -0
- package/.harness/skills/test-api.md +461 -0
- package/.harness/skills/test-e2e.md +431 -0
- package/.harness/skills/test-unit.md +649 -0
- package/.harness/skills/vue-frontend-build.md +344 -0
- package/.harness/specs/quality-feedback/implementation-guide.md +350 -0
- package/.harness/task-board.md +121 -0
- package/.harness/workflow/definition.yaml +504 -0
- package/.harness/workflow/validate.js +320 -0
- package/.harness/workflow/variants.yaml +253 -0
- package/README.md +237 -0
- package/bin/jsharness.js +53 -0
- package/lib/index.mjs +778 -0
- package/package.json +1 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
# Vue3 前端构建技能 (vue-frontend-build)
|
|
2
|
+
|
|
3
|
+
> **执行角色**: 开发者 Agent / CI Pipeline
|
|
4
|
+
> **适用项目**: Vue3 + TypeScript + Vite 前端项目
|
|
5
|
+
> **来源**: `files/frontend-project-conventions/SKILL.md`
|
|
6
|
+
> **归档日期**: 2026-05-21
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. 开发服务器启动
|
|
11
|
+
|
|
12
|
+
### 1.1 Vite Dev Server
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# 启动开发服务器(默认端口 5173)
|
|
16
|
+
npm run dev
|
|
17
|
+
|
|
18
|
+
# 指定端口
|
|
19
|
+
npm run dev -- --port 3000
|
|
20
|
+
|
|
21
|
+
# 指定主机(允许局域网访问)
|
|
22
|
+
npm run dev -- --host
|
|
23
|
+
|
|
24
|
+
# 使用 HTTPS(本地开发模拟生产)
|
|
25
|
+
npm run dev -- --https
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**通过标准**:
|
|
29
|
+
- ✅ 开发服务器正常启动无报错
|
|
30
|
+
- ✅ 页面可访问,组件正常渲染
|
|
31
|
+
- ✅ HMR(热模块替换)正常工作
|
|
32
|
+
|
|
33
|
+
### 1.2 开发代理配置
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// vite.config.ts — API 代理配置
|
|
37
|
+
export default defineConfig({
|
|
38
|
+
server: {
|
|
39
|
+
port: 5173,
|
|
40
|
+
proxy: {
|
|
41
|
+
'/api': {
|
|
42
|
+
target: 'http://localhost:8080',
|
|
43
|
+
changeOrigin: true,
|
|
44
|
+
rewrite: (path) => path.replace(/^\/api/, ''),
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 2. TypeScript 类型检查
|
|
54
|
+
|
|
55
|
+
### 2.1 类型检查命令
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# 类型检查(不生成输出文件)
|
|
59
|
+
npx vue-tsc --noEmit
|
|
60
|
+
|
|
61
|
+
# 仅检查指定文件
|
|
62
|
+
npx vue-tsc --noEmit src/pages/user/*.vue
|
|
63
|
+
|
|
64
|
+
# 监听模式(保存时自动检查)
|
|
65
|
+
npx vue-tsc --noEmit --watch
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**通过标准**:
|
|
69
|
+
- ✅ 零 Type Error(error 级别)
|
|
70
|
+
- ⚠️ warning 可以存在但建议修复
|
|
71
|
+
|
|
72
|
+
### 2.2 tsconfig.json 关键配置
|
|
73
|
+
|
|
74
|
+
```jsonc
|
|
75
|
+
{
|
|
76
|
+
"compilerOptions": {
|
|
77
|
+
"strict": true,
|
|
78
|
+
"noImplicitAny": true,
|
|
79
|
+
"strictNullChecks": true,
|
|
80
|
+
"skipLibCheck": true,
|
|
81
|
+
"jsx": "preserve",
|
|
82
|
+
"moduleResolution": "bundler",
|
|
83
|
+
"baseUrl": ".",
|
|
84
|
+
"paths": {
|
|
85
|
+
"@/*": ["src/*"]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 3. 生产构建
|
|
94
|
+
|
|
95
|
+
### 3.1 构建命令
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# 标准生产构建
|
|
99
|
+
npm run build
|
|
100
|
+
|
|
101
|
+
# 指定模式(使用 .env.production 配置)
|
|
102
|
+
npm run build -- --mode production
|
|
103
|
+
|
|
104
|
+
# 构建分析(查看包体积)
|
|
105
|
+
npm run build -- --mode analyze
|
|
106
|
+
|
|
107
|
+
# 清理缓存后构建
|
|
108
|
+
rm -rf node_modules/.vite && npm run build
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**通过标准**:
|
|
112
|
+
- ✅ 零构建错误
|
|
113
|
+
- ✅ 构建产物输出到 `dist/` 目录
|
|
114
|
+
- ✅ 包体积在合理范围内(首次加载 < 1MB)
|
|
115
|
+
|
|
116
|
+
### 3.2 Vite 构建优化配置
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// vite.config.ts — 生产优化
|
|
120
|
+
export default defineConfig({
|
|
121
|
+
build: {
|
|
122
|
+
target: 'es2020',
|
|
123
|
+
cssCodeSplit: true,
|
|
124
|
+
rollupOptions: {
|
|
125
|
+
output: {
|
|
126
|
+
manualChunks: {
|
|
127
|
+
// 将第三方库分离为独立 chunk
|
|
128
|
+
'vue-vendor': ['vue', 'vue-router', 'pinia'],
|
|
129
|
+
'element-plus': ['element-plus'],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
chunkSizeWarningLimit: 500, // KB
|
|
134
|
+
minify: 'terser', // terser 比 esbuild 压缩更彻底
|
|
135
|
+
terserOptions: {
|
|
136
|
+
compress: {
|
|
137
|
+
drop_console: true, // 生产移除 console
|
|
138
|
+
drop_debugger: true, // 生产移除 debugger
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### 3.3 构建产物结构
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
dist/
|
|
149
|
+
├── assets/
|
|
150
|
+
│ ├── index-[hash].js # 主 JS bundle
|
|
151
|
+
│ ├── index-[hash].css # 主 CSS 文件
|
|
152
|
+
│ └── vendor-[hash].js # 第三方库(如果配置了分包)
|
|
153
|
+
├── favicon.ico # 图标
|
|
154
|
+
└── index.html # 入口 HTML(自动注入资源链接)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 4. ESLint + Prettier 检查
|
|
160
|
+
|
|
161
|
+
### 4.1 ESLint 检查
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# 检查所有 .ts/.tsx/.vue 文件
|
|
165
|
+
npx eslint src/ --ext .ts,.tsx,.vue
|
|
166
|
+
|
|
167
|
+
# 只检查 error 级别问题
|
|
168
|
+
npx eslint src/ --ext .ts,.tsx,.vue --max-warnings 0
|
|
169
|
+
|
|
170
|
+
# 自动修复能修复的问题
|
|
171
|
+
npx eslint src/ --ext .ts,.tsx,.vue --fix
|
|
172
|
+
|
|
173
|
+
# 指定文件/目录检查
|
|
174
|
+
npx eslint src/pages/user/UserProfile.vue
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**ESLint 规则重点** (前端项目必须遵守):
|
|
178
|
+
- ✅ 无 error
|
|
179
|
+
- ✅ 禁止裸 any (`@typescript-eslint/no-explicit-any`)
|
|
180
|
+
- ✅ 禁止 console.log 残留 (`no-console`)
|
|
181
|
+
- ✅ Vue 组件使用 Composition API (`vue/no-deprecated-options-api`)
|
|
182
|
+
|
|
183
|
+
### 4.2 Prettier 格式化
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# 检查格式是否符合规范
|
|
187
|
+
npx prettier --check "src/**/*.{ts,tsx,vue,json}"
|
|
188
|
+
|
|
189
|
+
# 格式化所有文件
|
|
190
|
+
npx prettier --write "src/**/*.{ts,tsx,vue,json}"
|
|
191
|
+
|
|
192
|
+
# 格式化指定目录
|
|
193
|
+
npx prettier --write "src/components/**/*.vue"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Prettier 配置要点** (.prettierrc):
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"semi": true,
|
|
200
|
+
"singleQuote": true,
|
|
201
|
+
"tabWidth": 2,
|
|
202
|
+
"trailingComma": "all",
|
|
203
|
+
"printWidth": 100,
|
|
204
|
+
"vueIndentScriptAndStyle": false,
|
|
205
|
+
"endOfLine": "lf"
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 4.3 一键检查脚本
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
// package.json scripts
|
|
213
|
+
{
|
|
214
|
+
"lint": "eslint src/ --ext .ts,.tsx,.vue --max-warnings 0",
|
|
215
|
+
"lint:fix": "eslint src/ --ext .ts,.tsx,.vue --fix",
|
|
216
|
+
"format": "prettier --write \"src/**/*.{ts,tsx,vue,json}\"",
|
|
217
|
+
"format:check": "prettier --check \"src/**/*.{ts,tsx,vue,json}\""
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## 5. 单元测试(Vitest)
|
|
224
|
+
|
|
225
|
+
### 5.1 运行测试
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
# 运行全部测试
|
|
229
|
+
npm run test
|
|
230
|
+
|
|
231
|
+
# 监听模式
|
|
232
|
+
npm run test:watch
|
|
233
|
+
|
|
234
|
+
# 运行单个测试文件
|
|
235
|
+
npx vitest run src/utils/formatDate.test.ts
|
|
236
|
+
|
|
237
|
+
# 运行包含关键字的测试
|
|
238
|
+
npx vitest run -t "UserProfile"
|
|
239
|
+
|
|
240
|
+
# 生成覆盖率报告
|
|
241
|
+
npx vitest run --coverage
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### 5.2 Vitest 配置要点
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
// vitest.config.ts
|
|
248
|
+
import { defineConfig } from 'vitest/config';
|
|
249
|
+
import vue from '@vitejs/plugin-vue';
|
|
250
|
+
import path from 'path';
|
|
251
|
+
|
|
252
|
+
export default defineConfig({
|
|
253
|
+
plugins: [vue()],
|
|
254
|
+
test: {
|
|
255
|
+
globals: true,
|
|
256
|
+
environment: 'jsdom', // DOM API 支持(Vue Test Utils 需要)
|
|
257
|
+
setupFiles: ['./src/test/setup.ts'],
|
|
258
|
+
coverage: {
|
|
259
|
+
provider: 'v8', // 使用 v8 覆盖率引擎
|
|
260
|
+
reporter: ['text', 'html', 'lcov'],
|
|
261
|
+
include: ['src/**/*.ts', 'src/**/*.tsx'],
|
|
262
|
+
exclude: ['src/types/**', 'src/test/**'],
|
|
263
|
+
thresholds: {
|
|
264
|
+
lines: 80,
|
|
265
|
+
functions: 75,
|
|
266
|
+
branches: 70,
|
|
267
|
+
statements: 80,
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
resolve: {
|
|
272
|
+
alias: {
|
|
273
|
+
'@': path.resolve(__dirname, 'src'),
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**覆盖率目标**:
|
|
280
|
+
|
|
281
|
+
| 文件类型 | 行覆盖率 | 分支覆盖率 |
|
|
282
|
+
|---------|---------|-----------|
|
|
283
|
+
| 工具函数 (utils/) | ≥ 90% | ≥ 85% |
|
|
284
|
+
| Composables | ≥ 80% | ≥ 75% |
|
|
285
|
+
| Store (Pinia) | ≥ 75% | ≥ 70% |
|
|
286
|
+
| 组件渲染逻辑 | ≥ 70% | ≥ 60% |
|
|
287
|
+
|
|
288
|
+
### 5.3 Vue Test Utils 标准用法
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { describe, it, expect } from 'vitest';
|
|
292
|
+
import { mount } from '@vue/test-utils';
|
|
293
|
+
import UserProfile from './UserProfile.vue';
|
|
294
|
+
|
|
295
|
+
describe('UserProfile', () => {
|
|
296
|
+
it('正确显示用户名称', () => {
|
|
297
|
+
const wrapper = mount(UserProfile, {
|
|
298
|
+
props: { name: '张三' },
|
|
299
|
+
});
|
|
300
|
+
expect(wrapper.text()).toContain('张三');
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
it('点击编辑按钮触发 emit', async () => {
|
|
304
|
+
const wrapper = mount(UserProfile);
|
|
305
|
+
await wrapper.find('[data-test="edit-btn"]').trigger('click');
|
|
306
|
+
expect(wrapper.emitted('update')).toBeTruthy();
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## 6. 构建产物优化检查
|
|
314
|
+
|
|
315
|
+
### 6.1 体积分析
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# 使用 rollup-plugin-visualizer 分析包体积
|
|
319
|
+
npm run build -- --mode analyze
|
|
320
|
+
# → 自动打开浏览器可视化图表
|
|
321
|
+
|
|
322
|
+
# 或者使用命令行工具
|
|
323
|
+
npx vite-bundle-visualizer
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### 6.2 优化目标清单
|
|
327
|
+
|
|
328
|
+
| 指标 | 目标值 | 说明 |
|
|
329
|
+
|------|--------|------|
|
|
330
|
+
| 首次 JS 加载 | < 300KB (gzip) | 主要 chunk 大小 |
|
|
331
|
+
| CSS 总大小 | < 50KB (gzip) | 全部样式合计 |
|
|
332
|
+
| 静态资源 | 按需懒加载 | 图片、字体等 |
|
|
333
|
+
| chunk 数量 | 合理拆分 | 避免过多请求也避免单一大文件 |
|
|
334
|
+
| Lighthouse Performance | ≥ 90 分 | 生产部署后检测 |
|
|
335
|
+
|
|
336
|
+
### 6.3 常见体积问题及解决方案
|
|
337
|
+
|
|
338
|
+
| 问题 | 原因 | 方案 |
|
|
339
|
+
|------|------|------|
|
|
340
|
+
| Element Plus 全量引入 | 默认导入全部组件 | 改按需引入 (`unplugin-vue-components`) |
|
|
341
|
+
| Moment.js 体积大 | 含大量语言包 | 替换为 dayjs(API 兼容)|
|
|
342
|
+
| 图片未压缩 | 直接放入源码目录 | 使用 image-webpack-loader 或 CDN |
|
|
343
|
+
| Lodash 全量引入 | import _ from 'lodash' | 改按需 import (`lodash-es`) |
|
|
344
|
+
| 字体文件过大 | 引入中文字体全集 | 使用子集化字体或系统字体 |
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# Quality Feedback 反馈闭环系统
|
|
2
|
+
|
|
3
|
+
> **目的**: 让 AI 的产出从「做完」升级为「做对」
|
|
4
|
+
> **核心机制**: 自动化验证 → 问题归因 → 智能打回 → 度量追踪 → 持续改进
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. 验证报告标准化输出格式
|
|
9
|
+
|
|
10
|
+
所有 Gate 检查结果统一输出为标准化 JSON:
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"report_id": "gate-{timestamp}-{random}",
|
|
15
|
+
"timestamp": "2026-05-20T22:00:00Z",
|
|
16
|
+
"tool": "harness-gate v1.0.0",
|
|
17
|
+
"overall_status": "pass | warning | fail",
|
|
18
|
+
|
|
19
|
+
"categories": [
|
|
20
|
+
{
|
|
21
|
+
"category_id": "A",
|
|
22
|
+
"category_name": "静态规范",
|
|
23
|
+
"status": "pass",
|
|
24
|
+
"score": "95% (19/20)",
|
|
25
|
+
"issues_count": 1,
|
|
26
|
+
"issues": [
|
|
27
|
+
{
|
|
28
|
+
"code": "A3",
|
|
29
|
+
"severity": "warning",
|
|
30
|
+
"file": "src/components/Header.tsx",
|
|
31
|
+
"line": 23,
|
|
32
|
+
"message": "console.log 残留",
|
|
33
|
+
"suggestion": "移除调试语句或在 Gate 白名单中登记"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
|
|
39
|
+
"baseline_comparison": null,
|
|
40
|
+
|
|
41
|
+
"metadata": {
|
|
42
|
+
"source_branch": "feature/user-profile-123",
|
|
43
|
+
"target_branch": "develop",
|
|
44
|
+
"committer": "developer-agent",
|
|
45
|
+
"duration_ms": 4500
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 2. 问题自动归因分析逻辑
|
|
51
|
+
|
|
52
|
+
### 归因分类树
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Gate 报告发现问题
|
|
56
|
+
│
|
|
57
|
+
├── 类型判断 ──────────────────────────┐
|
|
58
|
+
│ ├── 代码质量问题 (A类) │ → 归因: 开发者 Agent
|
|
59
|
+
│ │ ├── 命名不规范 │
|
|
60
|
+
│ │ ├── 复杂度过高 │
|
|
61
|
+
│ │ └── DRY 违反 │
|
|
62
|
+
│ │ │
|
|
63
|
+
│ ├── 流程违规问题 (B类) │ → 归因: 对应角色 + PM
|
|
64
|
+
│ │ ├── Commit 格式错误 │
|
|
65
|
+
│ │ └── 缺少文档更新 │
|
|
66
|
+
│ │ │
|
|
67
|
+
│ ├── 安全红线问题 (C/D类) │ → 归因: 开发者 + 升级安全审查
|
|
68
|
+
│ │ ├── 凭证泄露 │
|
|
69
|
+
│ │ ├── 注入漏洞 │
|
|
70
|
+
│ │ └── CVE 依赖 │
|
|
71
|
+
│ │ │
|
|
72
|
+
│ ├── 测试不足问题 (E/C类) │ → 归因: 开发者(单测) + Tester(E2E)
|
|
73
|
+
│ │ ├── 覆盖率下降 │
|
|
74
|
+
│ │ ├── 关键路径无测试 │
|
|
75
|
+
│ │ └── 测试质量低 │
|
|
76
|
+
│ │ │
|
|
77
|
+
│ └── 一致性问题 (E类) │ → 归因: 开发者 + dev-map 维护者
|
|
78
|
+
│ ├── CHANGELOG 未更新 │
|
|
79
|
+
│ └── dev-map 过期 │
|
|
80
|
+
│ │
|
|
81
|
+
└── 根因深度分析 ───────────────┐
|
|
82
|
+
├── 是否首次出现? │
|
|
83
|
+
│ ├── 是 → 新引入的问题 │
|
|
84
|
+
│ └── 否 → 回归问题 │
|
|
85
|
+
├── 是否与基线对比? │
|
|
86
|
+
│ └── REGRESSION 标记 │
|
|
87
|
+
└── 是否影响其他模块? │
|
|
88
|
+
└── 影响面评估 │
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 自动归因引擎伪代码
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
function analyzeIssues(gateReport) {
|
|
95
|
+
const attributions = [];
|
|
96
|
+
|
|
97
|
+
for (const issue of gateReport.allIssues) {
|
|
98
|
+
const attribution = {
|
|
99
|
+
issue: issue,
|
|
100
|
+
rootCause: classifyRootCause(issue),
|
|
101
|
+
responsibleAgent: determineResponsibleAgent(issue),
|
|
102
|
+
severityLevel: assessImpact(issue),
|
|
103
|
+
suggestedAction: generateSuggestedAction(issue),
|
|
104
|
+
isRegression: checkAgainstBaseline(issue)
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
attributions.push(attribution);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 生成汇总
|
|
111
|
+
return {
|
|
112
|
+
summary: groupByAgent(attributions),
|
|
113
|
+
regressionCount: attributions.filter(a => a.isRegression).length,
|
|
114
|
+
blockingIssues: attributions.filter(a => a.severityLevel === 'critical'),
|
|
115
|
+
recommendedActions: prioritizeActions(attributions)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## 3. 自动打回规则引擎
|
|
121
|
+
|
|
122
|
+
### 打回条件(任一满足即触发自动打回)
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
auto_reject_rules:
|
|
126
|
+
# === 绝对打回(无条件执行)===
|
|
127
|
+
absolute_rejects:
|
|
128
|
+
- condition: "category == D AND severity == error"
|
|
129
|
+
reason: "🔴 安全红线违反 — 必须立即修复并重新提交"
|
|
130
|
+
target_agent: developer
|
|
131
|
+
escalation: true # 同时通知技术负责人
|
|
132
|
+
|
|
133
|
+
- condition: "baseline_comparison.regression == true AND affected_tests > 5"
|
|
134
|
+
reason: "🔴 测试覆盖率严重回归 — 修复后重新提交"
|
|
135
|
+
target_agent: developer
|
|
136
|
+
|
|
137
|
+
- condition: "any issue with code == A7" # Secret 泄露
|
|
138
|
+
reason: "🔴 发现可能的凭证泄露!立即处理!"
|
|
139
|
+
target_agent: developer
|
|
140
|
+
block_merge: true # 阻止合并
|
|
141
|
+
|
|
142
|
+
# === 有条件打回(可配置阈值)===
|
|
143
|
+
conditional_rejects:
|
|
144
|
+
- condition: "total_error_issues >= 3"
|
|
145
|
+
reason: "多个检查类别未通过,建议整体 review 后重新提交"
|
|
146
|
+
require_review_before_resubmit: true
|
|
147
|
+
|
|
148
|
+
- condition: "coverage_drop_percentage > 10"
|
|
149
|
+
reason: "测试覆盖率下降超过 10%,需要补充测试"
|
|
150
|
+
target_agent: developer
|
|
151
|
+
|
|
152
|
+
- condition: "new_security_findings_count > 0"
|
|
153
|
+
reason: "发现新的安全问题,需要安全审查后重提"
|
|
154
|
+
target_agent: developer
|
|
155
|
+
extra_reviewer: security-reviewer
|
|
156
|
+
|
|
157
|
+
# === 警告但不打回 ===
|
|
158
|
+
warnings_only:
|
|
159
|
+
- condition: "warnings_count <= 2"
|
|
160
|
+
action: "标记 WARNING,允许合并但需在下一迭代修复"
|
|
161
|
+
track_as_tech_debt: true
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 打回通知模板
|
|
165
|
+
|
|
166
|
+
```markdown
|
|
167
|
+
## 🔁 Harness 自动打回通知
|
|
168
|
+
|
|
169
|
+
**PR**: #{number} — {title}
|
|
170
|
+
**触发时间**: {timestamp}
|
|
171
|
+
**打回原因**: {reject_reason}
|
|
172
|
+
|
|
173
|
+
### 问题清单
|
|
174
|
+
{issues_list_table}
|
|
175
|
+
|
|
176
|
+
### 需要操作
|
|
177
|
+
1. 查看 Gate 报告: `{report_link}`
|
|
178
|
+
2. 按优先级修复上述问题
|
|
179
|
+
3. 重新运行 `node .harness/gate/index.js`
|
|
180
|
+
4. 确认全部 PASS 后重新提交 PR Review
|
|
181
|
+
|
|
182
|
+
### 如有疑问
|
|
183
|
+
- 打回规则参考: `.harness/rules/global/process-discipline.md`
|
|
184
|
+
- 联系 PM 或闸门总控 Agent 申诉
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## 4. 度量指标收集与存储
|
|
188
|
+
|
|
189
|
+
### 过程指标(Process Metrics)
|
|
190
|
+
|
|
191
|
+
```yaml
|
|
192
|
+
process_metrics:
|
|
193
|
+
# 交付效率
|
|
194
|
+
cycle_time:
|
|
195
|
+
description: "需求接收到交付的总天数"
|
|
196
|
+
calculation: "(delivery_date - received_date) in days"
|
|
197
|
+
target: "<= 7 days"
|
|
198
|
+
alert_threshold: "> 14 days"
|
|
199
|
+
|
|
200
|
+
lead_time:
|
|
201
|
+
description: "进入开发到合入主分支的天数"
|
|
202
|
+
target: "<= 5 days"
|
|
203
|
+
|
|
204
|
+
# 质量指标
|
|
205
|
+
gate_pass_rate:
|
|
206
|
+
description: "Gate 首次通过率"
|
|
207
|
+
formula: "(first_attempt_passes / total_attempts) × 100"
|
|
208
|
+
target: "> 80%"
|
|
209
|
+
|
|
210
|
+
rollback_rate:
|
|
211
|
+
description: "被打回重新处理的比率"
|
|
212
|
+
formula: "(rejected_tasks / total_completed_tasks) × 100"
|
|
213
|
+
target: "< 15%"
|
|
214
|
+
|
|
215
|
+
rework_cycles:
|
|
216
|
+
description: "平均每个任务的返工次数"
|
|
217
|
+
target: "< 1.5"
|
|
218
|
+
|
|
219
|
+
# 合规指标
|
|
220
|
+
process_compliance_rate:
|
|
221
|
+
description: "流程纪律遵守率"
|
|
222
|
+
formula: "(compliant_actions / total_actions) × 100"
|
|
223
|
+
target: "> 95%"
|
|
224
|
+
|
|
225
|
+
security_incidents:
|
|
226
|
+
description: "安全相关问题的数量(应为 0)"
|
|
227
|
+
target: "= 0"
|
|
228
|
+
|
|
229
|
+
# 质量指标
|
|
230
|
+
quality_metrics:
|
|
231
|
+
test_coverage_avg:
|
|
232
|
+
description: "平均测试覆盖率"
|
|
233
|
+
collection_source: "gate category C"
|
|
234
|
+
|
|
235
|
+
code_quality_score:
|
|
236
|
+
description: "代码审查加权平均分"
|
|
237
|
+
collection_source: "code review reports"
|
|
238
|
+
|
|
239
|
+
defect_escape_rate:
|
|
240
|
+
description: "逃逸到生产环境的 Bug 数量 / 总交付数"
|
|
241
|
+
target: "< 5%"
|
|
242
|
+
|
|
243
|
+
security_vulnerability_count:
|
|
244
|
+
description: "已知安全漏洞数量(按严重度分级)"
|
|
245
|
+
collection_source: "npm audit + gate category D"
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### 度量数据存储
|
|
249
|
+
|
|
250
|
+
```javascript
|
|
251
|
+
// metrics/store.js — 度量数据存储模块
|
|
252
|
+
|
|
253
|
+
class MetricsStore {
|
|
254
|
+
constructor() {
|
|
255
|
+
this.storage = '.harness/data/metrics.json';
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* 记录一次 Gate 结果
|
|
260
|
+
*/
|
|
261
|
+
recordGateResult(report) {
|
|
262
|
+
const entry = {
|
|
263
|
+
timestamp: report.timestamp,
|
|
264
|
+
report_id: report.report_id,
|
|
265
|
+
overall_status: report.overall_status,
|
|
266
|
+
scores: this.extractScores(report),
|
|
267
|
+
issues_summary: {
|
|
268
|
+
total: report.totalIssues,
|
|
269
|
+
byCategory: this.groupByCategory(report),
|
|
270
|
+
bySeverity: this.groupBySeverity(report)
|
|
271
|
+
},
|
|
272
|
+
baseline_delta: report.baselineComparison?.regression ? 'REGRESSION' :
|
|
273
|
+
report.baselineComparison?.improvement ? 'IMPROVEMENT' : 'STABLE',
|
|
274
|
+
metadata: report.metadata
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
this.appendToHistory(entry);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* 生成周报数据
|
|
282
|
+
*/
|
|
283
|
+
generateWeeklyReport(startDate, endDate) {
|
|
284
|
+
const data = this.queryRange(startDate, endDate);
|
|
285
|
+
return {
|
|
286
|
+
period: `${startDate} ~ ${endDate}`,
|
|
287
|
+
summary: {
|
|
288
|
+
total_gates: data.length,
|
|
289
|
+
pass_rate: this.calcPassRate(data),
|
|
290
|
+
avg_score: this.calcAvgScore(data),
|
|
291
|
+
top_failure_categories: this.topFailures(data, 5),
|
|
292
|
+
trend: this.calcTrend(data),
|
|
293
|
+
regression_events: data.filter(d => d.baseline_delta === 'REGRESSION').length,
|
|
294
|
+
process_violations: this.countViolations(data)
|
|
295
|
+
},
|
|
296
|
+
recommendations: this.generateRecommendations(data)
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## 5. 周报自动生成功能
|
|
303
|
+
|
|
304
|
+
### 周报模板
|
|
305
|
+
|
|
306
|
+
```markdown
|
|
307
|
+
# 📊 Harness Engineering 周报
|
|
308
|
+
|
|
309
|
+
**周期**: {week_range}
|
|
310
|
+
**生成时间**: {generated_at}
|
|
311
|
+
**自动生成**: ✅ 由 Quality Feedback 系统生成
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## 📈 本周概览
|
|
316
|
+
|
|
317
|
+
| 指标 | 本周数值 | 目标值 | 趋势 vs 上周 | 状态 |
|
|
318
|
+
|------|---------|--------|-------------|------|
|
|
319
|
+
| 完成交付数 | {delivered_count} | ≥3 | {delta} | {status} |
|
|
320
|
+
| 平均交付周期 | {avg_cycle} 天 | ≤7 | {delta} | {status} |
|
|
321
|
+
| Gate 通过率 | {pass_rate}% | ≥80% | {delta} | {status} |
|
|
322
|
+
| 打回率 | {rollback_rate}% | <15% | {delta} | {status} |
|
|
323
|
+
| 测试覆盖率 | {avg_coverage}% | ≥80% | {delta} | {status} |
|
|
324
|
+
| 流程违规次数 | {violations} | =0 | {delta} | {status} |
|
|
325
|
+
|
|
326
|
+
## 🔥 Top 5 失败类别
|
|
327
|
+
|
|
328
|
+
1. **{cat_1_name}** — {count} 次 ({pct}%)
|
|
329
|
+
- 主要原因: {reason_1}
|
|
330
|
+
|
|
331
|
+
2. **{cat_2_name}** — {count} 次 ({pct}%)
|
|
332
|
+
|
|
333
|
+
...
|
|
334
|
+
|
|
335
|
+
## ⚠️ 需要关注
|
|
336
|
+
|
|
337
|
+
- {alert_1}: {description}
|
|
338
|
+
- {alert_2}: {description}
|
|
339
|
+
|
|
340
|
+
## 💡 改进建议
|
|
341
|
+
|
|
342
|
+
基于本周数据分析:
|
|
343
|
+
1. {suggestion_1}
|
|
344
|
+
2. {suggestion_2}
|
|
345
|
+
3. {suggestion_3}
|
|
346
|
+
|
|
347
|
+
## 📋 下周重点
|
|
348
|
+
|
|
349
|
+
{next_week_focus_from_pm}
|
|
350
|
+
```
|