@dommaker/harness 0.6.0 → 0.7.1
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 +212 -28
- package/bin/harness.js +47 -8
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +4 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/spec.d.ts +31 -0
- package/dist/cli/commands/spec.d.ts.map +1 -0
- package/dist/cli/commands/spec.js +169 -0
- package/dist/cli/commands/spec.js.map +1 -0
- package/dist/core/constraints/definitions.d.ts.map +1 -1
- package/dist/core/constraints/definitions.js +5 -2
- package/dist/core/constraints/definitions.js.map +1 -1
- package/dist/core/constraints/index.d.ts +2 -0
- package/dist/core/constraints/index.d.ts.map +1 -1
- package/dist/core/constraints/index.js +7 -1
- package/dist/core/constraints/index.js.map +1 -1
- package/dist/core/constraints/interceptor.d.ts +37 -0
- package/dist/core/constraints/interceptor.d.ts.map +1 -0
- package/dist/core/constraints/interceptor.js +176 -0
- package/dist/core/constraints/interceptor.js.map +1 -0
- package/dist/core/project-config-loader.d.ts +4 -0
- package/dist/core/project-config-loader.d.ts.map +1 -1
- package/dist/core/project-config-loader.js +62 -9
- package/dist/core/project-config-loader.js.map +1 -1
- package/dist/core/spec/index.d.ts +7 -0
- package/dist/core/spec/index.d.ts.map +1 -0
- package/dist/core/spec/index.js +23 -0
- package/dist/core/spec/index.js.map +1 -0
- package/dist/core/spec/validator.d.ts +78 -0
- package/dist/core/spec/validator.d.ts.map +1 -0
- package/dist/core/spec/validator.js +372 -0
- package/dist/core/spec/validator.js.map +1 -0
- package/dist/core/validators/passes-gate.d.ts +51 -1
- package/dist/core/validators/passes-gate.d.ts.map +1 -1
- package/dist/core/validators/passes-gate.js +90 -0
- package/dist/core/validators/passes-gate.js.map +1 -1
- package/dist/extensions/long-running/constraints.d.ts +38 -0
- package/dist/extensions/long-running/constraints.d.ts.map +1 -0
- package/dist/extensions/long-running/constraints.js +153 -0
- package/dist/extensions/long-running/constraints.js.map +1 -0
- package/dist/extensions/long-running/index.d.ts +30 -0
- package/dist/extensions/long-running/index.d.ts.map +1 -0
- package/dist/extensions/long-running/index.js +50 -0
- package/dist/extensions/long-running/index.js.map +1 -0
- package/dist/extensions/long-running/types.d.ts +154 -0
- package/dist/extensions/long-running/types.d.ts.map +1 -0
- package/dist/extensions/long-running/types.js +9 -0
- package/dist/extensions/long-running/types.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/dist/presets/index.d.ts +1 -0
- package/dist/presets/index.d.ts.map +1 -1
- package/dist/presets/index.js +6 -1
- package/dist/presets/index.js.map +1 -1
- package/dist/presets/long-running.d.ts +33 -0
- package/dist/presets/long-running.d.ts.map +1 -0
- package/dist/presets/long-running.js +52 -0
- package/dist/presets/long-running.js.map +1 -0
- package/dist/types/constraint.d.ts +1 -1
- package/dist/types/constraint.d.ts.map +1 -1
- package/dist/types/constraint.js.map +1 -1
- package/dist/types/enforcement.d.ts +42 -0
- package/dist/types/enforcement.d.ts.map +1 -0
- package/dist/types/enforcement.js +6 -0
- package/dist/types/enforcement.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/passes-gate.d.ts +20 -0
- package/dist/types/passes-gate.d.ts.map +1 -1
- package/dist/types/project-config.d.ts +22 -9
- package/dist/types/project-config.d.ts.map +1 -1
- package/dist/types/spec.d.ts +85 -0
- package/dist/types/spec.d.ts.map +1 -0
- package/dist/types/spec.js +8 -0
- package/dist/types/spec.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @dommaker/harness
|
|
2
2
|
|
|
3
|
-
> 通用工程约束框架 -
|
|
3
|
+
> 通用工程约束框架 - 铁律系统、检查点验证、测试门控、拦截器
|
|
4
4
|
|
|
5
5
|
## 简介
|
|
6
6
|
|
|
@@ -10,13 +10,14 @@
|
|
|
10
10
|
|
|
11
11
|
| 功能 | 说明 |
|
|
12
12
|
|------|------|
|
|
13
|
-
| **铁律系统** |
|
|
13
|
+
| **铁律系统** | 16 条内置约束(4 Iron Laws + 10 Guidelines + 2 Tips) |
|
|
14
14
|
| **检查点验证** | 验证工作流步骤的结果是否符合预期 |
|
|
15
15
|
| **测试门控** | 禁止自评通过,必须通过真实测试 |
|
|
16
|
+
| **拦截器** | 抽象拦截框架,自动执行 enforcement(v0.7+) |
|
|
16
17
|
| **Session 管理** | 启动检查点 + 结束状态管理 |
|
|
17
18
|
| **预设系统** | 提供 strict/standard/relaxed 三种预设 |
|
|
18
|
-
| **Execution Trace** |
|
|
19
|
-
| **项目级自定义约束** | 扩展/覆盖内置约束,无需 fork
|
|
19
|
+
| **Execution Trace** | 轻量记录约束检查,异常检测,诊断系统 |
|
|
20
|
+
| **项目级自定义约束** | 扩展/覆盖内置约束,无需 fork |
|
|
20
21
|
| **CLI 工具** | 命令行工具执行检查 |
|
|
21
22
|
|
|
22
23
|
## 安装
|
|
@@ -46,12 +47,27 @@ npx harness init --preset standard
|
|
|
46
47
|
# 初始化项目配置
|
|
47
48
|
harness init --preset standard
|
|
48
49
|
|
|
50
|
+
# 输出配置代码片段(不创建文件)
|
|
51
|
+
harness init --print-snippets
|
|
52
|
+
|
|
49
53
|
# 检查铁律
|
|
50
54
|
harness check
|
|
51
55
|
|
|
52
56
|
# 列出所有铁律
|
|
53
57
|
harness check --list
|
|
54
58
|
|
|
59
|
+
# 查看状态(统计、异常、建议)
|
|
60
|
+
harness status
|
|
61
|
+
|
|
62
|
+
# 查看详细状态
|
|
63
|
+
harness status --detail
|
|
64
|
+
|
|
65
|
+
# 只显示异常
|
|
66
|
+
harness status --anomalies
|
|
67
|
+
|
|
68
|
+
# 一键执行诊断+提案流程
|
|
69
|
+
harness flow
|
|
70
|
+
|
|
55
71
|
# 验证检查点
|
|
56
72
|
harness validate
|
|
57
73
|
|
|
@@ -61,12 +77,10 @@ harness passes-gate
|
|
|
61
77
|
# 生成报告
|
|
62
78
|
harness report
|
|
63
79
|
|
|
64
|
-
#
|
|
65
|
-
harness traces stats
|
|
66
|
-
harness traces summary
|
|
67
|
-
harness traces anomalies
|
|
68
|
-
harness traces report # 生成完整报告
|
|
69
|
-
harness traces clean # 清理旧 trace 文件
|
|
80
|
+
# [已弃用] 请使用 harness status
|
|
81
|
+
harness traces stats
|
|
82
|
+
harness traces summary
|
|
83
|
+
harness traces anomalies
|
|
70
84
|
```
|
|
71
85
|
|
|
72
86
|
### 3. 在 CI 中使用
|
|
@@ -83,7 +97,48 @@ jobs:
|
|
|
83
97
|
- run: npx harness passes-gate
|
|
84
98
|
```
|
|
85
99
|
|
|
86
|
-
###
|
|
100
|
+
### 5. Spec 验证
|
|
101
|
+
|
|
102
|
+
验证架构文档、模块定义、API 定义等 Spec 文件:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# 验证所有 Spec 文件
|
|
106
|
+
harness spec
|
|
107
|
+
|
|
108
|
+
# 验证暂存文件(pre-commit)
|
|
109
|
+
harness spec --staged
|
|
110
|
+
|
|
111
|
+
# 验证指定文件
|
|
112
|
+
harness spec --file ARCHITECTURE.md
|
|
113
|
+
|
|
114
|
+
# 使用自定义 Schema
|
|
115
|
+
harness spec --schema ./my-specs/schemas
|
|
116
|
+
|
|
117
|
+
# 列出支持的 Spec 类型
|
|
118
|
+
harness spec list
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**项目自定义 Schema**:
|
|
122
|
+
|
|
123
|
+
项目可以定义自己的 Spec Schema,在 `src/specs/schemas/index.ts` 中导出 `validate` 函数:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
// src/specs/schemas/index.ts
|
|
127
|
+
import { z } from 'zod';
|
|
128
|
+
|
|
129
|
+
export const ArchitectureSchema = z.object({
|
|
130
|
+
name: z.string(),
|
|
131
|
+
version: z.string(),
|
|
132
|
+
modules: z.array(z.string()),
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
export async function validate(content: string, filePath: string) {
|
|
136
|
+
// 解析并验证内容
|
|
137
|
+
// 返回 SpecValidationResult
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### 6. 在代码中使用
|
|
87
142
|
|
|
88
143
|
```typescript
|
|
89
144
|
import {
|
|
@@ -115,23 +170,102 @@ const cleaner = new CleanStateManager();
|
|
|
115
170
|
const cleanResult = await cleaner.onSessionEnd(workDir, sessionInfo);
|
|
116
171
|
```
|
|
117
172
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
173
|
+
### 5. 使用拦截器(v0.7+)
|
|
174
|
+
|
|
175
|
+
拦截器自动执行 enforcement,无需手动调用检查 API:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
import {
|
|
179
|
+
interceptor,
|
|
180
|
+
registerExecutor,
|
|
181
|
+
interceptOperation,
|
|
182
|
+
claimOperation,
|
|
183
|
+
type EnforcementExecutor,
|
|
184
|
+
type ConstraintContext,
|
|
185
|
+
} from '@dommaker/harness';
|
|
186
|
+
|
|
187
|
+
// 1. 注册执行器(使用者实现具体逻辑)
|
|
188
|
+
registerExecutor('verify-completion', {
|
|
189
|
+
description: '验证完成声明:运行测试命令',
|
|
190
|
+
supportedParams: ['command', 'timeout'],
|
|
191
|
+
async execute(context) {
|
|
192
|
+
// 使用者自定义验证逻辑
|
|
193
|
+
const result = await exec('npm test', { cwd: context.projectPath });
|
|
194
|
+
return {
|
|
195
|
+
passed: result.success,
|
|
196
|
+
evidence: result.stdout,
|
|
197
|
+
};
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// 2. 在关键操作前拦截
|
|
202
|
+
try {
|
|
203
|
+
// 拦截 task_completion_claim 操作
|
|
204
|
+
// 自动查找适用的约束并执行对应的 enforcement
|
|
205
|
+
await claimOperation('task_completion_claim', {
|
|
206
|
+
operation: 'task_completion_claim',
|
|
207
|
+
projectPath: '/path/to/project',
|
|
208
|
+
sessionId: 'session-123',
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// 拦截通过,可以宣布完成
|
|
212
|
+
await announceCompletion();
|
|
213
|
+
} catch (e) {
|
|
214
|
+
// 拦截失败,铁律违规
|
|
215
|
+
console.error('必须先验证才能完成');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 3. 查询拦截结果(不抛异常)
|
|
219
|
+
const result = await interceptOperation('task_completion_claim', context);
|
|
220
|
+
if (result.passed) {
|
|
221
|
+
console.log('✅ 通过拦截');
|
|
222
|
+
} else {
|
|
223
|
+
console.log('❌ 约束违规:', result.violations);
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**拦截器 vs 手动检查**:
|
|
228
|
+
|
|
229
|
+
| 方式 | 特点 |
|
|
230
|
+
|------|------|
|
|
231
|
+
| 手动检查 | `checkConstraints()` 需要手动调用 API |
|
|
232
|
+
| 拦截器 | 自动执行 enforcement,抽象框架,使用者实现逻辑 |
|
|
233
|
+
|
|
234
|
+
**内置 enforcement IDs**:
|
|
235
|
+
|
|
236
|
+
| enforcement | 说明 |
|
|
237
|
+
|-------------|------|
|
|
238
|
+
| verify-completion | 验证完成声明:运行测试 |
|
|
239
|
+
| verify-e2e | 验证端到端测试 |
|
|
240
|
+
| debug-systematic | 系统性调试检查 |
|
|
241
|
+
| reuse-first | 复用优先检查 |
|
|
242
|
+
| update-capabilities | CAPABILITIES.md 同步检查 |
|
|
243
|
+
| tdd-cycle | TDD 循环检查 |
|
|
244
|
+
| passes-gate | 测试门控 |
|
|
245
|
+
| checkpoint-required | 检查点必须通过 |
|
|
246
|
+
| check-coverage | 覆盖率检查 |
|
|
247
|
+
| require-discussion | 设计决策讨论检查 |
|
|
248
|
+
|
|
249
|
+
## 内置约束(16 条)
|
|
250
|
+
|
|
251
|
+
| ID | 规则 | 层级 | 严重性 |
|
|
252
|
+
|---|------|------|:------:|
|
|
253
|
+
| `no_bypass_checkpoint` | 禁止跳过检查点 | iron_law | 🔴 error |
|
|
254
|
+
| `no_self_approval` | 禁止自评通过 | iron_law | 🔴 error |
|
|
255
|
+
| `no_completion_without_verification` | 完成必须有验证证据 | iron_law | 🔴 error |
|
|
256
|
+
| `no_test_simplification` | 禁止擅自简化测试 | iron_law | 🔴 error |
|
|
257
|
+
| `no_fix_without_root_cause` | 修复前必须找到根因 | guideline | 🔴 error |
|
|
258
|
+
| `no_code_without_test` | 写代码前必须有测试 | guideline | 🔴 error |
|
|
259
|
+
| `no_any_type` | 禁止使用 any 类型 | guideline | 🟡 warning |
|
|
260
|
+
| `simplest_solution_first` | 优先选择最简方案 | guideline | 🟡 warning |
|
|
261
|
+
| `no_creation_without_reuse_check` | 创建前必须检查可复用 | guideline | 🟡 warning |
|
|
262
|
+
| `capability_sync` | 代码变更必须更新 CAPABILITIES.md | guideline | 🟡 warning |
|
|
263
|
+
| `no_simplification_without_approval` | 不能擅自简化逻辑 | guideline | 🟡 warning |
|
|
264
|
+
| `no_skill_without_test` | 创建技能前必须有测试 | guideline | 🟡 warning |
|
|
265
|
+
| `test_coverage_required` | 测试覆盖率必须达标 | guideline | 🟡 warning |
|
|
266
|
+
| `design_decision_requires_discussion` | 设计决策必须先讨论 | guideline | 🟡 warning |
|
|
267
|
+
| `readme_required` | 新模块必须有 README | tip | 🔵 info |
|
|
268
|
+
| `doc_required_for_public_api` | 公共 API 必须有文档 | tip | 🔵 info |
|
|
135
269
|
|
|
136
270
|
## 预设系统
|
|
137
271
|
|
|
@@ -141,6 +275,56 @@ const cleanResult = await cleaner.onSessionEnd(workDir, sessionInfo);
|
|
|
141
275
|
| `standard` | 标准模式,推荐使用 |
|
|
142
276
|
| `relaxed` | 宽松模式,警告不阻止 |
|
|
143
277
|
|
|
278
|
+
## 自定义约束(v0.4+)
|
|
279
|
+
|
|
280
|
+
### 扩展例外(v0.6+)
|
|
281
|
+
|
|
282
|
+
使用 `extend_exceptions` 追加例外,保留内置例外:
|
|
283
|
+
|
|
284
|
+
```yaml
|
|
285
|
+
# .harness/custom-constraints.yml
|
|
286
|
+
custom_constraints:
|
|
287
|
+
no_fix_without_root_cause:
|
|
288
|
+
extend_exceptions:
|
|
289
|
+
- my_special_case_1
|
|
290
|
+
- my_special_case_2
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
结果:内置例外 + 新增例外
|
|
294
|
+
|
|
295
|
+
### 完全覆盖
|
|
296
|
+
|
|
297
|
+
使用 `exceptions` 完全覆盖内置例外:
|
|
298
|
+
|
|
299
|
+
```yaml
|
|
300
|
+
# .harness/custom-constraints.yml
|
|
301
|
+
custom_constraints:
|
|
302
|
+
no_fix_without_root_cause:
|
|
303
|
+
level: guideline
|
|
304
|
+
rule: Do not fix without root cause
|
|
305
|
+
message: 禁止没有根因分析就修复
|
|
306
|
+
trigger: bug_fix
|
|
307
|
+
exceptions:
|
|
308
|
+
- my_only_exception
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
结果:只使用自定义例外
|
|
312
|
+
|
|
313
|
+
### 混合模式
|
|
314
|
+
|
|
315
|
+
同时使用 `exceptions` 和 `extend_exceptions`:
|
|
316
|
+
|
|
317
|
+
```yaml
|
|
318
|
+
custom_constraints:
|
|
319
|
+
no_fix_without_root_cause:
|
|
320
|
+
exceptions:
|
|
321
|
+
- my_new_exception
|
|
322
|
+
extend_exceptions:
|
|
323
|
+
- another_exception
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
结果:内置例外 + my_new_exception + another_exception
|
|
327
|
+
|
|
144
328
|
## 项目模板
|
|
145
329
|
|
|
146
330
|
提供多种项目模板:
|
package/bin/harness.js
CHANGED
|
@@ -18,7 +18,9 @@ const {
|
|
|
18
18
|
diagnoseCommand,
|
|
19
19
|
proposeCommand,
|
|
20
20
|
status,
|
|
21
|
-
flow
|
|
21
|
+
flow,
|
|
22
|
+
specValidate,
|
|
23
|
+
listSpecTypes
|
|
22
24
|
} = require('../dist/cli/commands/index');
|
|
23
25
|
|
|
24
26
|
const program = new Command();
|
|
@@ -26,7 +28,7 @@ const program = new Command();
|
|
|
26
28
|
program
|
|
27
29
|
.name('harness')
|
|
28
30
|
.description('通用工程约束框架 - 铁律系统、检查点验证、测试门控、执行追踪')
|
|
29
|
-
.version('0.
|
|
31
|
+
.version('0.7.0');
|
|
30
32
|
|
|
31
33
|
// ========================================
|
|
32
34
|
// harness check
|
|
@@ -114,16 +116,21 @@ program
|
|
|
114
116
|
});
|
|
115
117
|
|
|
116
118
|
// ========================================
|
|
117
|
-
// harness traces
|
|
119
|
+
// harness traces [DEPRECATED]
|
|
118
120
|
// ========================================
|
|
119
121
|
program
|
|
120
122
|
.command('traces [subcommand]')
|
|
121
|
-
.description('
|
|
123
|
+
.description('[已弃用] 请使用 harness status')
|
|
122
124
|
.option('--hours <n>', '分析最近 N 小时', '1')
|
|
123
125
|
.option('--constraint <id>', '过滤约束 ID')
|
|
124
126
|
.option('--format <format>', '输出格式 (json/text)', 'text')
|
|
125
127
|
.option('--max-age-days <n>', '清理超过 N 天的文件', '30')
|
|
126
128
|
.action(async (subcommand, options, command) => {
|
|
129
|
+
console.log('⚠️ harness traces 已弃用,请使用 harness status');
|
|
130
|
+
console.log(' harness status # 查看统计');
|
|
131
|
+
console.log(' harness status --detail # 查看详情');
|
|
132
|
+
console.log(' harness status --anomalies # 查看异常');
|
|
133
|
+
console.log();
|
|
127
134
|
const sub = subcommand || 'stats';
|
|
128
135
|
await tracesCommand(sub, {
|
|
129
136
|
hours: parseInt(options.hours, 10),
|
|
@@ -134,17 +141,20 @@ program
|
|
|
134
141
|
});
|
|
135
142
|
|
|
136
143
|
// ========================================
|
|
137
|
-
// harness diagnose
|
|
144
|
+
// harness diagnose [DEPRECATED]
|
|
138
145
|
// ========================================
|
|
139
146
|
program
|
|
140
147
|
.command('diagnose [subcommand]')
|
|
141
|
-
.description('
|
|
148
|
+
.description('[已弃用] 请使用 harness flow')
|
|
142
149
|
.option('--hours <n>', '分析最近 N 小时', '24')
|
|
143
150
|
.option('--constraint <id>', '过滤约束 ID')
|
|
144
151
|
.option('--anomaly <id>', '特定异常 ID')
|
|
145
152
|
.option('--format <format>', '输出格式 (json/text)', 'text')
|
|
146
153
|
.option('--save', '保存诊断结果', false)
|
|
147
154
|
.action(async (subcommand, options, command) => {
|
|
155
|
+
console.log('⚠️ harness diagnose 已弃用,请使用 harness flow');
|
|
156
|
+
console.log(' harness flow # 一键执行诊断 + 提案流程');
|
|
157
|
+
console.log();
|
|
148
158
|
const sub = subcommand || 'list';
|
|
149
159
|
await diagnoseCommand(sub, {
|
|
150
160
|
hours: parseInt(options.hours, 10),
|
|
@@ -156,11 +166,11 @@ program
|
|
|
156
166
|
});
|
|
157
167
|
|
|
158
168
|
// ========================================
|
|
159
|
-
// harness propose
|
|
169
|
+
// harness propose [DEPRECATED]
|
|
160
170
|
// ========================================
|
|
161
171
|
program
|
|
162
172
|
.command('propose [subcommand]')
|
|
163
|
-
.description('
|
|
173
|
+
.description('[已弃用] 请使用 harness flow')
|
|
164
174
|
.option('--diagnosis <id>', '诊断 ID')
|
|
165
175
|
.option('--status <status>', '过滤状态')
|
|
166
176
|
.option('--format <format>', '输出格式 (json/text)', 'text')
|
|
@@ -169,6 +179,9 @@ program
|
|
|
169
179
|
.option('--reject', '拒绝提案', false)
|
|
170
180
|
.option('--comment <text>', '审核意见')
|
|
171
181
|
.action(async (subcommand, options, command) => {
|
|
182
|
+
console.log('⚠️ harness propose 已弃用,请使用 harness flow');
|
|
183
|
+
console.log(' harness flow # 一键执行诊断 + 提案流程');
|
|
184
|
+
console.log();
|
|
172
185
|
const sub = subcommand || 'list';
|
|
173
186
|
await proposeCommand(sub, {
|
|
174
187
|
diagnosisId: options.diagnosis,
|
|
@@ -219,5 +232,31 @@ program
|
|
|
219
232
|
});
|
|
220
233
|
});
|
|
221
234
|
|
|
235
|
+
// ========================================
|
|
236
|
+
// harness spec
|
|
237
|
+
// ========================================
|
|
238
|
+
program
|
|
239
|
+
.command('spec [subcommand]')
|
|
240
|
+
.description('Spec 验证命令')
|
|
241
|
+
.option('-s, --schema <path>', 'Schema 路径(项目定义)')
|
|
242
|
+
.option('--staged', '只验证暂存文件', false)
|
|
243
|
+
.option('-f, --file <path>', '验证指定文件')
|
|
244
|
+
.option('-p, --project-path <path>', '项目路径')
|
|
245
|
+
.option('-v, --verbose', '详细输出', false)
|
|
246
|
+
.action(async (subcommand, options, command) => {
|
|
247
|
+
if (subcommand === 'list') {
|
|
248
|
+
listSpecTypes();
|
|
249
|
+
} else {
|
|
250
|
+
// 默认执行 validate
|
|
251
|
+
await specValidate({
|
|
252
|
+
schema: options.schema,
|
|
253
|
+
staged: options.staged,
|
|
254
|
+
file: options.file || (subcommand && !subcommand.startsWith('-') ? subcommand : undefined),
|
|
255
|
+
projectPath: options.projectPath,
|
|
256
|
+
verbose: options.verbose,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
222
261
|
// 解析命令行参数
|
|
223
262
|
program.parse();
|
|
@@ -11,4 +11,5 @@ export { diagnoseCommand } from './diagnose';
|
|
|
11
11
|
export { proposeCommand } from './propose';
|
|
12
12
|
export { status, type StatusOptions } from './status';
|
|
13
13
|
export { flow, type FlowOptions } from './flow';
|
|
14
|
+
export { specValidate, listSpecTypes, type SpecValidateOptions } from './spec';
|
|
14
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* CLI 命令导出
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.flow = exports.status = exports.proposeCommand = exports.diagnoseCommand = exports.tracesCommand = exports.report = exports.init = exports.checkCoverage = exports.runPassesGate = exports.createExampleCheckpoint = exports.validate = exports.listLaws = exports.check = void 0;
|
|
6
|
+
exports.listSpecTypes = exports.specValidate = exports.flow = exports.status = exports.proposeCommand = exports.diagnoseCommand = exports.tracesCommand = exports.report = exports.init = exports.checkCoverage = exports.runPassesGate = exports.createExampleCheckpoint = exports.validate = exports.listLaws = exports.check = void 0;
|
|
7
7
|
var check_1 = require("./check");
|
|
8
8
|
Object.defineProperty(exports, "check", { enumerable: true, get: function () { return check_1.check; } });
|
|
9
9
|
Object.defineProperty(exports, "listLaws", { enumerable: true, get: function () { return check_1.listLaws; } });
|
|
@@ -27,4 +27,7 @@ var status_1 = require("./status");
|
|
|
27
27
|
Object.defineProperty(exports, "status", { enumerable: true, get: function () { return status_1.status; } });
|
|
28
28
|
var flow_1 = require("./flow");
|
|
29
29
|
Object.defineProperty(exports, "flow", { enumerable: true, get: function () { return flow_1.flow; } });
|
|
30
|
+
var spec_1 = require("./spec");
|
|
31
|
+
Object.defineProperty(exports, "specValidate", { enumerable: true, get: function () { return spec_1.specValidate; } });
|
|
32
|
+
Object.defineProperty(exports, "listSpecTypes", { enumerable: true, get: function () { return spec_1.listSpecTypes; } });
|
|
30
33
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,iCAA6D;AAApD,8FAAA,KAAK,OAAA;AAAE,iGAAA,QAAQ,OAAA;AACxB,uCAAqF;AAA5E,oGAAA,QAAQ,OAAA;AAAE,mHAAA,uBAAuB,OAAA;AAC1C,6CAAqF;AAA5E,4GAAA,aAAa,OAAA;AAAE,4GAAA,aAAa,OAAA;AACrC,+BAAgD;AAAvC,4FAAA,IAAI,OAAA;AACb,mCAAsD;AAA7C,gGAAA,MAAM,OAAA;AACf,mCAAyC;AAAhC,uGAAA,aAAa,OAAA;AACtB,uCAA6C;AAApC,2GAAA,eAAe,OAAA;AACxB,qCAA2C;AAAlC,yGAAA,cAAc,OAAA;AACvB,mCAAsD;AAA7C,gGAAA,MAAM,OAAA;AACf,+BAAgD;AAAvC,4FAAA,IAAI,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/commands/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,iCAA6D;AAApD,8FAAA,KAAK,OAAA;AAAE,iGAAA,QAAQ,OAAA;AACxB,uCAAqF;AAA5E,oGAAA,QAAQ,OAAA;AAAE,mHAAA,uBAAuB,OAAA;AAC1C,6CAAqF;AAA5E,4GAAA,aAAa,OAAA;AAAE,4GAAA,aAAa,OAAA;AACrC,+BAAgD;AAAvC,4FAAA,IAAI,OAAA;AACb,mCAAsD;AAA7C,gGAAA,MAAM,OAAA;AACf,mCAAyC;AAAhC,uGAAA,aAAa,OAAA;AACtB,uCAA6C;AAApC,2GAAA,eAAe,OAAA;AACxB,qCAA2C;AAAlC,yGAAA,cAAc,OAAA;AACvB,mCAAsD;AAA7C,gGAAA,MAAM,OAAA;AACf,+BAAgD;AAAvC,4FAAA,IAAI,OAAA;AACb,+BAA+E;AAAtE,oGAAA,YAAY,OAAA;AAAE,qGAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* harness spec validate 命令
|
|
3
|
+
*
|
|
4
|
+
* 验证 Spec 文件格式
|
|
5
|
+
*
|
|
6
|
+
* 设计原则:
|
|
7
|
+
* - 框架不包含具体 Schema 定义
|
|
8
|
+
* - 项目需要定义自己的 Spec Schema
|
|
9
|
+
* - 支持动态加载项目的 Schema
|
|
10
|
+
*/
|
|
11
|
+
export interface SpecValidateOptions {
|
|
12
|
+
/** Schema 路径(项目定义) */
|
|
13
|
+
schema?: string;
|
|
14
|
+
/** 只验证暂存文件 */
|
|
15
|
+
staged?: boolean;
|
|
16
|
+
/** 验证指定文件 */
|
|
17
|
+
file?: string;
|
|
18
|
+
/** 项目路径 */
|
|
19
|
+
projectPath?: string;
|
|
20
|
+
/** 详细输出 */
|
|
21
|
+
verbose?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 执行 Spec 验证
|
|
25
|
+
*/
|
|
26
|
+
export declare function specValidate(options: SpecValidateOptions): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* 列出支持的 Spec 类型
|
|
29
|
+
*/
|
|
30
|
+
export declare function listSpecTypes(): void;
|
|
31
|
+
//# sourceMappingURL=spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,MAAM,WAAW,mBAAmB;IAClC,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW;IACX,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsC9E;AA2ED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CASpC"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* harness spec validate 命令
|
|
4
|
+
*
|
|
5
|
+
* 验证 Spec 文件格式
|
|
6
|
+
*
|
|
7
|
+
* 设计原则:
|
|
8
|
+
* - 框架不包含具体 Schema 定义
|
|
9
|
+
* - 项目需要定义自己的 Spec Schema
|
|
10
|
+
* - 支持动态加载项目的 Schema
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
+
};
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
exports.specValidate = specValidate;
|
|
50
|
+
exports.listSpecTypes = listSpecTypes;
|
|
51
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const validator_1 = require("../../core/spec/validator");
|
|
54
|
+
/**
|
|
55
|
+
* 执行 Spec 验证
|
|
56
|
+
*/
|
|
57
|
+
async function specValidate(options) {
|
|
58
|
+
console.log(chalk_1.default.blue('📋 验证 Spec 文件...'));
|
|
59
|
+
const projectPath = options.projectPath || process.cwd();
|
|
60
|
+
const validator = validator_1.SpecValidator.getInstance();
|
|
61
|
+
// 设置 Schema 路径
|
|
62
|
+
if (options.schema) {
|
|
63
|
+
const absoluteSchemaPath = path.resolve(projectPath, options.schema);
|
|
64
|
+
validator.setConfig({ schemaPath: absoluteSchemaPath });
|
|
65
|
+
console.log(chalk_1.default.gray(`Schema 路径: ${absoluteSchemaPath}`));
|
|
66
|
+
}
|
|
67
|
+
let result;
|
|
68
|
+
// 单文件验证
|
|
69
|
+
if (options.file) {
|
|
70
|
+
const absoluteFilePath = path.resolve(projectPath, options.file);
|
|
71
|
+
console.log(chalk_1.default.gray(`验证文件: ${absoluteFilePath}`));
|
|
72
|
+
result = await validator.validateFile(absoluteFilePath);
|
|
73
|
+
printSingleResult(result, options.verbose);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// 批量验证
|
|
77
|
+
console.log(chalk_1.default.gray(`项目路径: ${projectPath}`));
|
|
78
|
+
console.log(chalk_1.default.gray(`仅暂存: ${options.staged ? '是' : '否'}`));
|
|
79
|
+
console.log();
|
|
80
|
+
result = await (0, validator_1.validateAllSpecs)(projectPath, options.staged);
|
|
81
|
+
// 打印结果
|
|
82
|
+
printBatchResult(result, options.verbose);
|
|
83
|
+
// 根据失败级别决定退出码
|
|
84
|
+
if (!options.staged && result.failed > 0) {
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 打印单个文件验证结果
|
|
90
|
+
*/
|
|
91
|
+
function printSingleResult(result, verbose) {
|
|
92
|
+
if (result.valid) {
|
|
93
|
+
console.log(chalk_1.default.green(`✅ ${result.file} 验证通过`));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
console.log(chalk_1.default.red(`❌ ${result.file} 验证失败`));
|
|
97
|
+
}
|
|
98
|
+
if (result.errors.length > 0) {
|
|
99
|
+
console.log();
|
|
100
|
+
console.log(chalk_1.default.red('错误:'));
|
|
101
|
+
for (const error of result.errors) {
|
|
102
|
+
console.log(chalk_1.default.red(` - ${error.path ? error.path + ': ' : ''}${error.message}`));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (result.warnings.length > 0) {
|
|
106
|
+
console.log();
|
|
107
|
+
console.log(chalk_1.default.yellow('警告:'));
|
|
108
|
+
for (const warning of result.warnings) {
|
|
109
|
+
console.log(chalk_1.default.yellow(` - ${warning.path ? warning.path + ': ' : ''}${warning.message}`));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (verbose && result.metrics) {
|
|
113
|
+
console.log();
|
|
114
|
+
console.log(chalk_1.default.gray('指标:'));
|
|
115
|
+
for (const [key, value] of Object.entries(result.metrics)) {
|
|
116
|
+
console.log(chalk_1.default.gray(` - ${key}: ${value}`));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* 打印批量验证结果
|
|
122
|
+
*/
|
|
123
|
+
function printBatchResult(result, verbose) {
|
|
124
|
+
// 汇总
|
|
125
|
+
console.log(chalk_1.default.bold('验证结果:'));
|
|
126
|
+
console.log(chalk_1.default.gray(` 总文件数: ${result.total}`));
|
|
127
|
+
console.log(chalk_1.default.green(` 通过: ${result.passed}`));
|
|
128
|
+
console.log(chalk_1.default.red(` 失败: ${result.failed}`));
|
|
129
|
+
console.log(chalk_1.default.yellow(` 警告: ${result.warnings}`));
|
|
130
|
+
console.log();
|
|
131
|
+
// 详细结果
|
|
132
|
+
if (verbose || result.failed > 0) {
|
|
133
|
+
for (const r of result.results) {
|
|
134
|
+
if (!r.valid || verbose) {
|
|
135
|
+
printSingleResult(r, verbose);
|
|
136
|
+
console.log();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// 成功提示
|
|
141
|
+
if (result.failed === 0 && result.total > 0) {
|
|
142
|
+
console.log(chalk_1.default.green('✅ 所有 Spec 文件验证通过'));
|
|
143
|
+
}
|
|
144
|
+
else if (result.total === 0) {
|
|
145
|
+
console.log(chalk_1.default.gray('没有找到 Spec 文件,跳过验证'));
|
|
146
|
+
console.log();
|
|
147
|
+
console.log(chalk_1.default.gray('提示: Spec 文件包括:'));
|
|
148
|
+
console.log(chalk_1.default.gray(' - ARCHITECTURE.md'));
|
|
149
|
+
console.log(chalk_1.default.gray(' - specs/ 目录下的 .yml/.yaml 文件'));
|
|
150
|
+
console.log();
|
|
151
|
+
console.log(chalk_1.default.gray('要定义自己的 Schema,请在项目中创建:'));
|
|
152
|
+
console.log(chalk_1.default.gray(' src/specs/schemas/index.ts'));
|
|
153
|
+
console.log(chalk_1.default.gray(' 导出 validate 函数'));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* 列出支持的 Spec 类型
|
|
158
|
+
*/
|
|
159
|
+
function listSpecTypes() {
|
|
160
|
+
console.log(chalk_1.default.blue('📋 支持的 Spec 类型:'));
|
|
161
|
+
console.log();
|
|
162
|
+
console.log(' architecture - ARCHITECTURE.md 架构文档');
|
|
163
|
+
console.log(' module - 模块定义(specs/modules/*.yml)');
|
|
164
|
+
console.log(' api - API 定义(specs/apis/*.yml)');
|
|
165
|
+
console.log(' custom - 自定义 Spec');
|
|
166
|
+
console.log();
|
|
167
|
+
console.log(chalk_1.default.gray('提示: 项目可以定义自己的 Schema 进行验证'));
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec.js","sourceRoot":"","sources":["../../../src/cli/commands/spec.ts"],"names":[],"mappings":"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"}
|