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.
Files changed (68) hide show
  1. package/.harness/README.md +199 -0
  2. package/.harness/agents/code-reviewer/contract.yaml +64 -0
  3. package/.harness/agents/developer/contract.yaml +72 -0
  4. package/.harness/agents/gate-controller/contract.yaml +64 -0
  5. package/.harness/agents/project-manager/contract.yaml +77 -0
  6. package/.harness/agents/prompt-templates.md +352 -0
  7. package/.harness/agents/requirements-analyst/contract.yaml +64 -0
  8. package/.harness/agents/solution-designer/contract.yaml +75 -0
  9. package/.harness/agents/tester/contract.yaml +92 -0
  10. package/.harness/config/models.yaml +67 -0
  11. package/.harness/dev-map/backend/api-definition.md +131 -0
  12. package/.harness/dev-map/backend/auth-security.md +131 -0
  13. package/.harness/dev-map/backend/conventions-java.md +471 -0
  14. package/.harness/dev-map/backend/conventions.md +192 -0
  15. package/.harness/dev-map/backend/database.md +106 -0
  16. package/.harness/dev-map/backend/structure.md +140 -0
  17. package/.harness/dev-map/decisions.md +275 -0
  18. package/.harness/dev-map/frontend/api-integration.md +139 -0
  19. package/.harness/dev-map/frontend/components.md +178 -0
  20. package/.harness/dev-map/frontend/conventions.md +416 -0
  21. package/.harness/dev-map/frontend/state-management.md +170 -0
  22. package/.harness/dev-map/frontend/structure.md +103 -0
  23. package/.harness/dev-map/overview.md +267 -0
  24. package/.harness/docs/integration-test-plan.md +248 -0
  25. package/.harness/docs/team-guidelines/README.md +161 -0
  26. package/.harness/docs/team-guidelines/arch-team.md +811 -0
  27. package/.harness/docs/team-guidelines/collaboration.md +556 -0
  28. package/.harness/docs/team-guidelines/pm-team.md +337 -0
  29. package/.harness/docs/team-guidelines/qa-team.md +562 -0
  30. package/.harness/docs/team-guidelines/rd-team.md +714 -0
  31. package/.harness/docs/training-materials.md +280 -0
  32. package/.harness/gate/baseline.js +220 -0
  33. package/.harness/gate/checks/build-gates-frontend.js +152 -0
  34. package/.harness/gate/checks/build-gates-java.js +155 -0
  35. package/.harness/gate/checks/build-gates.js +119 -0
  36. package/.harness/gate/checks/engineering-consistency.js +138 -0
  37. package/.harness/gate/checks/security-quality.js +129 -0
  38. package/.harness/gate/checks/static-compliance.js +313 -0
  39. package/.harness/gate/checks/test-compliance.js +114 -0
  40. package/.harness/gate/index.js +315 -0
  41. package/.harness/mcp/config.yaml +435 -0
  42. package/.harness/rules/global/coding-standard.md +232 -0
  43. package/.harness/rules/global/commit-convention.md +165 -0
  44. package/.harness/rules/global/process-discipline.md +192 -0
  45. package/.harness/rules/global/security-baseline.md +306 -0
  46. package/.harness/rules/project/frontend-vue3.md +293 -0
  47. package/.harness/rules/project/java-backend.md +460 -0
  48. package/.harness/rules/project/web-specific.md +231 -0
  49. package/.harness/skills/build.md +192 -0
  50. package/.harness/skills/code-review.md +251 -0
  51. package/.harness/skills/docker-build.md +227 -0
  52. package/.harness/skills/docs-update.md +164 -0
  53. package/.harness/skills/java-build.md +261 -0
  54. package/.harness/skills/lint-check.md +482 -0
  55. package/.harness/skills/task-board-maintenance.md +105 -0
  56. package/.harness/skills/test-api.md +461 -0
  57. package/.harness/skills/test-e2e.md +431 -0
  58. package/.harness/skills/test-unit.md +649 -0
  59. package/.harness/skills/vue-frontend-build.md +344 -0
  60. package/.harness/specs/quality-feedback/implementation-guide.md +350 -0
  61. package/.harness/task-board.md +121 -0
  62. package/.harness/workflow/definition.yaml +504 -0
  63. package/.harness/workflow/validate.js +320 -0
  64. package/.harness/workflow/variants.yaml +253 -0
  65. package/README.md +237 -0
  66. package/bin/jsharness.js +53 -0
  67. package/lib/index.mjs +778 -0
  68. package/package.json +1 -0
@@ -0,0 +1,315 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Harness Gate Scripts — 主入口
5
+ *
6
+ * 统一验证入口,整合所有检查模块,输出标准化报告。
7
+ *
8
+ * 使用方式:
9
+ * node .harness/gate/index.js # 完整检查
10
+ * node .harness/gate/index.js --save-baseline # 保存基线
11
+ * node .harness/gate/index.js --baseline # 对比基线
12
+ * node .harness/gate/index.js --check A # 只运行 A 类检查
13
+ * node .harness/gate/index.js --report json # JSON 格式输出
14
+ * node .harness/gate/index.js --output report.md # 输出到文件
15
+ */
16
+
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+
20
+ // ============================================================
21
+ // 配置与常量
22
+ // ============================================================
23
+
24
+ const GATE_ROOT = path.resolve(__dirname);
25
+ const CHECKS_DIR = path.join(GATE_ROOT, 'checks');
26
+ const BASELINE_FILE = path.join(process.cwd(), '.gate-baseline.json');
27
+ const REPORT_FILE = path.join(process.cwd(), '.gate-report.json');
28
+
29
+ // 检查类别定义(按执行顺序)
30
+ const CHECK_CATEGORIES = [
31
+ { id: 'A', name: '静态规范', module: 'static-compliance', weight: 20, failBlocks: true },
32
+ { id: 'B', name: '构建门槛', module: 'build-gates', weight: 25, failBlocks: true },
33
+ { id: 'C', name: '测试合规', module: 'test-compliance', weight: 25, failBlocks: true },
34
+ { id: 'D', name: '安全质量', module: 'security-quality', weight: 15, failBlocks: true }, // 安全红线
35
+ { id: 'E', name: '工程一致性', module: 'engineering-consistency', weight: 15, failBlocks: false }
36
+ ];
37
+
38
+ // ============================================================
39
+ // CLI 参数解析
40
+ // ============================================================
41
+
42
+ function parseArgs() {
43
+ const args = process.argv.slice(2);
44
+ const options = {
45
+ saveBaseline: args.includes('--save-baseline'),
46
+ useBaseline: args.includes('--baseline'),
47
+ checkOnly: null,
48
+ outputFormat: 'text',
49
+ outputFile: null,
50
+ verbose: args.includes('-v') || args.includes('--verbose')
51
+ };
52
+
53
+ for (let i = 0; i < args.length; i++) {
54
+ if (args[i] === '--check' && args[i + 1]) {
55
+ options.checkOnly = args[i + 1].toUpperCase();
56
+ }
57
+ if (args[i] === '--report' && args[i + 1]) {
58
+ options.outputFormat = args[i + 1].toLowerCase();
59
+ }
60
+ if (args[i] === '--output' && args[i + 1]) {
61
+ options.outputFile = args[i + 1];
62
+ }
63
+ }
64
+
65
+ return options;
66
+ }
67
+
68
+ // ============================================================
69
+ // 报告生成器
70
+ // ============================================================
71
+
72
+ class GateReport {
73
+ constructor() {
74
+ this.timestamp = new Date().toISOString();
75
+ this.tool = 'harness-gate v1.0.0';
76
+ this.options = parseArgs();
77
+ this.results = [];
78
+ this.overallStatus = 'pass';
79
+ this.duration = { start: Date.now(), end: null };
80
+
81
+ // 基线数据
82
+ this.baselineData = null;
83
+ this.baselineComparison = null;
84
+ }
85
+
86
+ /**
87
+ * 添加一个类别的结果
88
+ */
89
+ addCategoryResult(categoryId, result) {
90
+ this.results.push({ category: categoryId, ...result });
91
+ }
92
+
93
+ /**
94
+ * 计算总体状态
95
+ */
96
+ calculateOverall() {
97
+ this.duration.end = Date.now();
98
+
99
+ let hasFail = false;
100
+ let hasWarning = false;
101
+
102
+ for (const result of this.results) {
103
+ if (result.status === 'fail') hasFail = true;
104
+ else if (result.status === 'warning') hasWarning = true;
105
+
106
+ // D 类(安全)和 A/B/C 类 FAIL 直接导致门禁失败
107
+ const catConfig = CHECK_CATEGORIES.find(c => c.id === result.category);
108
+ if (catConfig?.failBlocks && result.status === 'fail') {
109
+ hasFail = true;
110
+ }
111
+ }
112
+
113
+ if (hasFail) this.overallStatus = 'fail';
114
+ else if (hasWarning) this.overallStatus = 'warning';
115
+ else this.overallStatus = 'pass';
116
+ }
117
+
118
+ /**
119
+ * 生成文本报告
120
+ */
121
+ toText() {
122
+ const lines = [];
123
+ lines.push('╔════════════════════════════════════════════╗');
124
+ lines.push('║ HARNESS ENGINEERING GATE REPORT ║');
125
+ lines.push('╠════════════════════════════════════════════╣');
126
+ lines.push(`║ 时间: ${this.timestamp.padEnd(34)}║`);
127
+ lines.push(`║ 状态: ${this._statusBadge(this.overallStatus).padEnd(33)}║`);
128
+ lines.push(`║ 耗时: ${((this.duration.end - this.duration.start) / 1000).toFixed(1)}s`.padEnd(40) + '║');
129
+ lines.push('╠════════════════════════════════════════════╣');
130
+
131
+ for (const result of this.results) {
132
+ const catName = `[${result.category}] ${CHECK_CATEGORIES.find(c => c.id === result.category)?.name || 'Unknown'}`;
133
+ lines.push(`║ ${catName.padEnd(38)}║`);
134
+ lines.push(`║ 状态: ${this._statusBadge(result.status).padEnd(33)}║`);
135
+ if (result.score !== undefined) {
136
+ lines.push(`║ 得分: ${String(result.score).padEnd(36)}║`);
137
+ }
138
+ if (result.issues && result.issues.length > 0) {
139
+ for (const issue of result.issues.slice(0, 10)) {
140
+ const line = ` ! ${issue.message || issue}`.substring(0, 38);
141
+ lines.push(`║${line.padEnd(39)}║`);
142
+ }
143
+ if (result.issues.length > 10) {
144
+ lines.push(`║ ... 还有 ${result.issues.length - 10} 个问题`.padEnd(40) + '║');
145
+ }
146
+ }
147
+ lines.push('╟──────────────────────────────────────────────╢');
148
+ }
149
+
150
+ if (this.baselineComparison) {
151
+ lines.push('║ 📊 基线对比 ║');
152
+ const bc = this.baselineComparison;
153
+ lines.push(`║ 回归: ${bc.regression ? '⚠️ YES' : '✅ NO'}`);
154
+ if (bc.details) {
155
+ for (const d of bc.details) {
156
+ lines.push(`║ ${d}`.padEnd(39) + '║');
157
+ }
158
+ }
159
+ lines.push('╟──────────────────────────────────────────────╢');
160
+ }
161
+
162
+ lines.push(`║ 结论: ${this._conclusionText().padEnd(35)}║`);
163
+ lines.push('╚════════════════════════════════════════════╝');
164
+
165
+ return lines.join('\n');
166
+ }
167
+
168
+ /**
169
+ * 生成 JSON 报告
170
+ */
171
+ toJSON() {
172
+ return {
173
+ timestamp: this.timestamp,
174
+ tool: this.tool,
175
+ overall_status: this.overallStatus,
176
+ duration_ms: this.duration.end - this.duration.start,
177
+ categories: this.results.map(r => ({
178
+ category_id: r.category,
179
+ status: r.status,
180
+ score: r.score,
181
+ issues_count: r.issues?.length || 0,
182
+ issues: r.issues || []
183
+ })),
184
+ baseline_comparison: this.baselineComparison
185
+ };
186
+ }
187
+
188
+ _statusBadge(status) {
189
+ switch (status) {
190
+ case 'pass': return '✅ PASS';
191
+ case 'warning': return '⚠️ WARNING';
192
+ case 'fail': return '❌ FAIL';
193
+ default: return `❓ ${status}`;
194
+ }
195
+ }
196
+
197
+ _conclusionText() {
198
+ switch (this.overallStatus) {
199
+ case 'pass': return '所有检查通过 ✅ 可以进入下一阶段';
200
+ case 'warning': return '存在警告 ⚠️ 建议修复后继续';
201
+ case 'fail': return '检查未通过 ❌ 必须修复后重新提交';
202
+ default: return '状态未知';
203
+ }
204
+ }
205
+ }
206
+
207
+ // ============================================================
208
+ // 主流程
209
+ // ============================================================
210
+
211
+ async function main() {
212
+ const options = parseArgs();
213
+ const report = new GateReport();
214
+
215
+ console.log('\n🚀 Harness Gate Scripts 启动...\n');
216
+
217
+ // 加载基线数据
218
+ if (options.useBaseline && fs.existsSync(BASELINE_FILE)) {
219
+ try {
220
+ report.baselineData = JSON.parse(fs.readFileSync(BASELINE_FILE, 'utf-8'));
221
+ console.log(`📊 已加载基线文件: ${BASELINE_FILE}\n`);
222
+ } catch (e) {
223
+ console.warn(`⚠️ 基线文件解析失败: ${e.message}`);
224
+ }
225
+ }
226
+
227
+ // 执行各检查模块
228
+ const checksToRun = options.checkOnly
229
+ ? CHECK_CATEGORIES.filter(c => c.id === options.checkOnly)
230
+ : CHECK_CATEGORIES;
231
+
232
+ if (checksToRun.length === 0) {
233
+ console.error(`❌ 未知的检查类别: ${options.checkOnly}。可用选项: ${CHECK_CATEGORIES.map(c => c.id).join(', ')}`);
234
+ process.exit(2);
235
+ }
236
+
237
+ for (const cat of checksToRun) {
238
+ console.log(`\n🔍 [${cat.id}] 运行 ${cat.name} 检查...`);
239
+
240
+ try {
241
+ const checkModulePath = path.join(CHECKS_DIR, `${cat.module}.js`);
242
+
243
+ if (!fs.existsSync(checkModulePath)) {
244
+ // 模块不存在时返回占位结果
245
+ report.addCategoryResult(cat.id, {
246
+ status: 'warning',
247
+ score: 'N/A',
248
+ issues: [`检查模块 ${cat.module}.js 尚未实现`]
249
+ });
250
+ console.log(` ⚠️ 模块未实现,跳过`);
251
+ continue;
252
+ }
253
+
254
+ // 动态加载并执行检查模块
255
+ const checkFn = require(checkModulePath);
256
+ const result = await typeof checkFn === 'function'
257
+ ? checkFn(options)
258
+ : (checkFn.run ? checkFn.run(options) : checkFn);
259
+
260
+ report.addCategoryResult(cat.id, result);
261
+ console.log(` 结果: ${report._statusBadge(result.status)}${result.score !== undefined ? ` | 得分: ${result.score}` : ''}${result.issues?.length ? ` | 问题数: ${result.issues.length}` : ''}`);
262
+
263
+ } catch (error) {
264
+ report.addCategoryResult(cat.id, {
265
+ status: 'error',
266
+ issues: [{ message: `检查执行异常: ${error.message}`, error }]
267
+ });
268
+ console.error(` ❌ 执行错误: ${error.message}`);
269
+ }
270
+ }
271
+
272
+ // 基线对比
273
+ if (report.baselineData && options.useBaseline) {
274
+ try {
275
+ const baselineModule = require(path.join(GATE_ROOT, 'baseline'));
276
+ report.baselineComparison = baselineModule.compare(report.toJSON(), report.baselineData);
277
+ } catch (e) {
278
+ // 基线对比可选,失败不阻塞
279
+ }
280
+ }
281
+
282
+ // 计算最终结果
283
+ report.calculateOverall();
284
+
285
+ // 输出报告
286
+ if (options.outputFormat === 'json') {
287
+ console.log(JSON.stringify(report.toJSON(), null, 2));
288
+ } else {
289
+ console.log('\n' + report.toText());
290
+ }
291
+
292
+ // 保存报告文件
293
+ const outputFile = options.outputFile || REPORT_FILE;
294
+ fs.writeFileSync(outputFile, JSON.stringify(report.toJSON(), null, 2));
295
+ console.log(`\n📄 报告已保存到: ${outputFile}`);
296
+
297
+ // 保存基线
298
+ if (options.saveBaseline) {
299
+ fs.writeFileSync(BASELINE_FILE, JSON.stringify(report.toJSON(), null, 2));
300
+ console.log(`💾 基线已保存到: ${BASELINE_FILE}`);
301
+ }
302
+
303
+ // 返回退出码
304
+ const shouldFail = report.overallStatus === 'fail';
305
+ console.log(`\n${shouldFail ? '❌ 门禁未通过' : '✅ 门禁通过'}`);
306
+ process.exit(shouldFail ? 1 : 0);
307
+ }
308
+
309
+ // 执行入口
310
+ main().catch(err => {
311
+ console.error('❌ Gate 脚本致命错误:', err);
312
+ process.exit(3);
313
+ });
314
+
315
+ module.exports = { GateReport, CHECK_CATEGORIES, parseArgs };