@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.
Files changed (81) hide show
  1. package/README.md +212 -28
  2. package/bin/harness.js +47 -8
  3. package/dist/cli/commands/index.d.ts +1 -0
  4. package/dist/cli/commands/index.d.ts.map +1 -1
  5. package/dist/cli/commands/index.js +4 -1
  6. package/dist/cli/commands/index.js.map +1 -1
  7. package/dist/cli/commands/spec.d.ts +31 -0
  8. package/dist/cli/commands/spec.d.ts.map +1 -0
  9. package/dist/cli/commands/spec.js +169 -0
  10. package/dist/cli/commands/spec.js.map +1 -0
  11. package/dist/core/constraints/definitions.d.ts.map +1 -1
  12. package/dist/core/constraints/definitions.js +5 -2
  13. package/dist/core/constraints/definitions.js.map +1 -1
  14. package/dist/core/constraints/index.d.ts +2 -0
  15. package/dist/core/constraints/index.d.ts.map +1 -1
  16. package/dist/core/constraints/index.js +7 -1
  17. package/dist/core/constraints/index.js.map +1 -1
  18. package/dist/core/constraints/interceptor.d.ts +37 -0
  19. package/dist/core/constraints/interceptor.d.ts.map +1 -0
  20. package/dist/core/constraints/interceptor.js +176 -0
  21. package/dist/core/constraints/interceptor.js.map +1 -0
  22. package/dist/core/project-config-loader.d.ts +4 -0
  23. package/dist/core/project-config-loader.d.ts.map +1 -1
  24. package/dist/core/project-config-loader.js +62 -9
  25. package/dist/core/project-config-loader.js.map +1 -1
  26. package/dist/core/spec/index.d.ts +7 -0
  27. package/dist/core/spec/index.d.ts.map +1 -0
  28. package/dist/core/spec/index.js +23 -0
  29. package/dist/core/spec/index.js.map +1 -0
  30. package/dist/core/spec/validator.d.ts +78 -0
  31. package/dist/core/spec/validator.d.ts.map +1 -0
  32. package/dist/core/spec/validator.js +372 -0
  33. package/dist/core/spec/validator.js.map +1 -0
  34. package/dist/core/validators/passes-gate.d.ts +51 -1
  35. package/dist/core/validators/passes-gate.d.ts.map +1 -1
  36. package/dist/core/validators/passes-gate.js +90 -0
  37. package/dist/core/validators/passes-gate.js.map +1 -1
  38. package/dist/extensions/long-running/constraints.d.ts +38 -0
  39. package/dist/extensions/long-running/constraints.d.ts.map +1 -0
  40. package/dist/extensions/long-running/constraints.js +153 -0
  41. package/dist/extensions/long-running/constraints.js.map +1 -0
  42. package/dist/extensions/long-running/index.d.ts +30 -0
  43. package/dist/extensions/long-running/index.d.ts.map +1 -0
  44. package/dist/extensions/long-running/index.js +50 -0
  45. package/dist/extensions/long-running/index.js.map +1 -0
  46. package/dist/extensions/long-running/types.d.ts +154 -0
  47. package/dist/extensions/long-running/types.d.ts.map +1 -0
  48. package/dist/extensions/long-running/types.js +9 -0
  49. package/dist/extensions/long-running/types.js.map +1 -0
  50. package/dist/index.d.ts +7 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +20 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/presets/index.d.ts +1 -0
  55. package/dist/presets/index.d.ts.map +1 -1
  56. package/dist/presets/index.js +6 -1
  57. package/dist/presets/index.js.map +1 -1
  58. package/dist/presets/long-running.d.ts +33 -0
  59. package/dist/presets/long-running.d.ts.map +1 -0
  60. package/dist/presets/long-running.js +52 -0
  61. package/dist/presets/long-running.js.map +1 -0
  62. package/dist/types/constraint.d.ts +1 -1
  63. package/dist/types/constraint.d.ts.map +1 -1
  64. package/dist/types/constraint.js.map +1 -1
  65. package/dist/types/enforcement.d.ts +42 -0
  66. package/dist/types/enforcement.d.ts.map +1 -0
  67. package/dist/types/enforcement.js +6 -0
  68. package/dist/types/enforcement.js.map +1 -0
  69. package/dist/types/index.d.ts +2 -0
  70. package/dist/types/index.d.ts.map +1 -1
  71. package/dist/types/index.js +4 -0
  72. package/dist/types/index.js.map +1 -1
  73. package/dist/types/passes-gate.d.ts +20 -0
  74. package/dist/types/passes-gate.d.ts.map +1 -1
  75. package/dist/types/project-config.d.ts +22 -9
  76. package/dist/types/project-config.d.ts.map +1 -1
  77. package/dist/types/spec.d.ts +85 -0
  78. package/dist/types/spec.d.ts.map +1 -0
  79. package/dist/types/spec.js +8 -0
  80. package/dist/types/spec.js.map +1 -0
  81. 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 条内置铁律,违规则阻止操作 |
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** | 轻量记录约束检查,异常检测,诊断系统(v0.3+) |
19
- | **项目级自定义约束** | 扩展/覆盖内置约束,无需 fork(v0.4+) |
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
- # Trace 分析(Execution Traces)
65
- harness traces stats # 查看 trace 文件统计
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
- ### 4. 在代码中使用
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
- ## 内置铁律(13 条)
119
-
120
- | ID | 规则 | 严重性 |
121
- |---|------|:------:|
122
- | `no_simplification_without_approval` | 不能擅自简化逻辑 | 🔴 error |
123
- | `no_fix_without_root_cause` | 修复前必须找到根因 | 🔴 error |
124
- | `no_completion_without_verification` | 完成必须有验证证据 | 🔴 error |
125
- | `no_skill_without_test` | 创建技能前必须有测试 | 🟡 warning |
126
- | `no_code_without_test` | 写代码前必须有测试 | 🔴 error |
127
- | `no_creation_without_reuse_check` | 创建前必须检查可复用 | 🟡 warning |
128
- | `capability_sync` | 代码变更必须更新 CAPABILITIES.md | 🟡 warning |
129
- | `no_any_type` | 禁止使用 any 类型 | 🟡 warning |
130
- | `no_bypass_checkpoint` | 禁止跳过检查点 | 🔴 error |
131
- | `test_coverage_required` | 测试覆盖率必须达标 | 🟡 warning |
132
- | `no_self_approval` | 禁止自评通过 | 🔴 error |
133
- | `doc_required_for_public_api` | 公共 API 必须有文档 | 🟡 warning |
134
- | `readme_required` | 新模块必须有 README | 🔵 info |
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.3.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('Execution Trace 分析')
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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"}