@dommaker/harness 1.9.0 → 1.10.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 (253) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +9 -12
  3. package/dist/cli/commands/check.d.ts +3 -3
  4. package/dist/cli/commands/check.d.ts.map +1 -1
  5. package/dist/cli/commands/check.js +41 -78
  6. package/dist/cli/commands/check.js.map +1 -1
  7. package/dist/cli/commands/constraints-report.d.ts +2 -10
  8. package/dist/cli/commands/constraints-report.d.ts.map +1 -1
  9. package/dist/cli/commands/constraints-report.js +4 -57
  10. package/dist/cli/commands/constraints-report.js.map +1 -1
  11. package/dist/cli/commands/constraints-retire.d.ts +9 -23
  12. package/dist/cli/commands/constraints-retire.d.ts.map +1 -1
  13. package/dist/cli/commands/constraints-retire.js +39 -121
  14. package/dist/cli/commands/constraints-retire.js.map +1 -1
  15. package/dist/cli/commands/constraints.d.ts +3 -8
  16. package/dist/cli/commands/constraints.d.ts.map +1 -1
  17. package/dist/cli/commands/constraints.js +8 -23
  18. package/dist/cli/commands/constraints.js.map +1 -1
  19. package/dist/cli/commands/definitions.js +2 -2
  20. package/dist/cli/commands/init.d.ts +0 -32
  21. package/dist/cli/commands/init.d.ts.map +1 -1
  22. package/dist/cli/commands/init.js +7 -149
  23. package/dist/cli/commands/init.js.map +1 -1
  24. package/dist/cli/commands/report.d.ts.map +1 -1
  25. package/dist/cli/commands/report.js +14 -17
  26. package/dist/cli/commands/report.js.map +1 -1
  27. package/dist/cli/commands/scaffold-templates.d.ts +0 -2
  28. package/dist/cli/commands/scaffold-templates.d.ts.map +1 -1
  29. package/dist/cli/commands/scaffold-templates.js +2 -37
  30. package/dist/cli/commands/scaffold-templates.js.map +1 -1
  31. package/dist/cli/commands/scaffold.d.ts +0 -2
  32. package/dist/cli/commands/scaffold.d.ts.map +1 -1
  33. package/dist/cli/commands/scaffold.js +0 -10
  34. package/dist/cli/commands/scaffold.js.map +1 -1
  35. package/dist/cli/commands/status.js +10 -10
  36. package/dist/cli/commands/status.js.map +1 -1
  37. package/dist/cli/commands/sync-docs/agents-syncer.d.ts +0 -2
  38. package/dist/cli/commands/sync-docs/agents-syncer.d.ts.map +1 -1
  39. package/dist/cli/commands/sync-docs/agents-syncer.js +4 -23
  40. package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -1
  41. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  42. package/dist/core/constraints/capabilities-parser.js +16 -4
  43. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  44. package/dist/core/constraints/checker.d.ts +15 -24
  45. package/dist/core/constraints/checker.d.ts.map +1 -1
  46. package/dist/core/constraints/checker.js +33 -72
  47. package/dist/core/constraints/checker.js.map +1 -1
  48. package/dist/core/constraints/checkers/docs-freshness.js +1 -1
  49. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  50. package/dist/core/constraints/checkers/governance-presence.d.ts +2 -1
  51. package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
  52. package/dist/core/constraints/checkers/governance-presence.js +4 -3
  53. package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
  54. package/dist/core/constraints/checkers/index.d.ts +1 -1
  55. package/dist/core/constraints/checkers/index.d.ts.map +1 -1
  56. package/dist/core/constraints/checkers/index.js +4 -8
  57. package/dist/core/constraints/checkers/index.js.map +1 -1
  58. package/dist/core/constraints/checkers/iron-flags.d.ts +3 -4
  59. package/dist/core/constraints/checkers/iron-flags.d.ts.map +1 -1
  60. package/dist/core/constraints/checkers/iron-flags.js +4 -5
  61. package/dist/core/constraints/checkers/iron-flags.js.map +1 -1
  62. package/dist/core/constraints/checkers/no-test-simplification.js +1 -1
  63. package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -1
  64. package/dist/core/constraints/checkers/types.d.ts +1 -1
  65. package/dist/core/constraints/checkers/types.js +1 -1
  66. package/dist/core/constraints/definitions/guidelines.d.ts +4 -4
  67. package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -1
  68. package/dist/core/constraints/definitions/guidelines.js +9 -25
  69. package/dist/core/constraints/definitions/guidelines.js.map +1 -1
  70. package/dist/core/constraints/definitions/iron-laws.d.ts +4 -4
  71. package/dist/core/constraints/definitions/iron-laws.d.ts.map +1 -1
  72. package/dist/core/constraints/definitions/iron-laws.js +10 -81
  73. package/dist/core/constraints/definitions/iron-laws.js.map +1 -1
  74. package/dist/core/constraints/definitions.d.ts +7 -9
  75. package/dist/core/constraints/definitions.d.ts.map +1 -1
  76. package/dist/core/constraints/definitions.js +13 -16
  77. package/dist/core/constraints/definitions.js.map +1 -1
  78. package/dist/core/constraints/index.d.ts +2 -5
  79. package/dist/core/constraints/index.d.ts.map +1 -1
  80. package/dist/core/constraints/index.js +3 -13
  81. package/dist/core/constraints/index.js.map +1 -1
  82. package/dist/core/constraints/injection-writer.d.ts +10 -38
  83. package/dist/core/constraints/injection-writer.d.ts.map +1 -1
  84. package/dist/core/constraints/injection-writer.js +17 -54
  85. package/dist/core/constraints/injection-writer.js.map +1 -1
  86. package/dist/core/constraints/run-env.d.ts +1 -10
  87. package/dist/core/constraints/run-env.d.ts.map +1 -1
  88. package/dist/core/constraints/run-env.js +1 -22
  89. package/dist/core/constraints/run-env.js.map +1 -1
  90. package/dist/core/constraints/usage-report.d.ts +5 -7
  91. package/dist/core/constraints/usage-report.d.ts.map +1 -1
  92. package/dist/core/constraints/usage-report.js +5 -10
  93. package/dist/core/constraints/usage-report.js.map +1 -1
  94. package/dist/core/effective-constraints.d.ts +12 -22
  95. package/dist/core/effective-constraints.d.ts.map +1 -1
  96. package/dist/core/effective-constraints.js +13 -30
  97. package/dist/core/effective-constraints.js.map +1 -1
  98. package/dist/core/index.d.ts +2 -2
  99. package/dist/core/index.d.ts.map +1 -1
  100. package/dist/core/index.js +3 -9
  101. package/dist/core/index.js.map +1 -1
  102. package/dist/core/project-config-loader.d.ts +4 -42
  103. package/dist/core/project-config-loader.d.ts.map +1 -1
  104. package/dist/core/project-config-loader.js +16 -125
  105. package/dist/core/project-config-loader.js.map +1 -1
  106. package/dist/core/validators/passes-gate.d.ts +2 -2
  107. package/dist/core/validators/passes-gate.js +6 -6
  108. package/dist/core/validators/passes-gate.js.map +1 -1
  109. package/dist/index.d.ts +7 -10
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +9 -18
  112. package/dist/index.js.map +1 -1
  113. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  114. package/dist/monitoring/trace-analyzer.js +11 -12
  115. package/dist/monitoring/trace-analyzer.js.map +1 -1
  116. package/dist/monitoring/traces.d.ts +4 -4
  117. package/dist/monitoring/traces.d.ts.map +1 -1
  118. package/dist/monitoring/traces.js +8 -8
  119. package/dist/monitoring/traces.js.map +1 -1
  120. package/dist/presets/standard.d.ts +8 -10
  121. package/dist/presets/standard.d.ts.map +1 -1
  122. package/dist/presets/standard.js +10 -16
  123. package/dist/presets/standard.js.map +1 -1
  124. package/dist/types/constraint.d.ts +24 -35
  125. package/dist/types/constraint.d.ts.map +1 -1
  126. package/dist/types/constraint.js +8 -7
  127. package/dist/types/constraint.js.map +1 -1
  128. package/dist/types/passes-gate.d.ts +5 -5
  129. package/dist/types/passes-gate.d.ts.map +1 -1
  130. package/dist/types/project-config.d.ts +8 -66
  131. package/dist/types/project-config.d.ts.map +1 -1
  132. package/dist/types/project-config.js +3 -2
  133. package/dist/types/project-config.js.map +1 -1
  134. package/dist/types/trace.d.ts +8 -10
  135. package/dist/types/trace.d.ts.map +1 -1
  136. package/package.json +2 -2
  137. package/src/CONTEXT.md +2 -2
  138. package/src/__tests__/checker-extra.test.ts +37 -61
  139. package/src/__tests__/checker.test.ts +10 -115
  140. package/src/__tests__/effective-constraints.test.ts +18 -83
  141. package/src/__tests__/iron-laws.test.ts +71 -90
  142. package/src/__tests__/passes-gate-check.test.ts +2 -2
  143. package/src/__tests__/project-config-loader-extra.test.ts +22 -123
  144. package/src/__tests__/project-config-loader.test.ts +5 -33
  145. package/src/__tests__/public-exports.test.ts +1 -7
  146. package/src/__tests__/public-type-surface.test.ts +2 -5
  147. package/src/__tests__/public-value-surface.test.ts +1 -7
  148. package/src/__tests__/skip-semantics.test.ts +21 -37
  149. package/src/__tests__/trace-analyzer-extra.test.ts +14 -14
  150. package/src/__tests__/trace-analyzer.test.ts +21 -21
  151. package/src/__tests__/trace-collector.test.ts +22 -22
  152. package/src/__tests__/traces.test.ts +27 -28
  153. package/src/cli/commands/CONTEXT.md +9 -9
  154. package/src/cli/commands/__tests__/check-read-count.test.ts +4 -15
  155. package/src/cli/commands/__tests__/check-skip-output.test.ts +14 -14
  156. package/src/cli/commands/__tests__/check.test.ts +14 -31
  157. package/src/cli/commands/__tests__/constraints-report.test.ts +12 -80
  158. package/src/cli/commands/__tests__/constraints-retire.test.ts +42 -231
  159. package/src/cli/commands/__tests__/init-governance-io.test.ts +12 -58
  160. package/src/cli/commands/__tests__/init-ondisk.test.ts +12 -20
  161. package/src/cli/commands/__tests__/init.test.ts +0 -11
  162. package/src/cli/commands/__tests__/project-path-anchoring.test.ts +2 -2
  163. package/src/cli/commands/__tests__/report-extra.test.ts +4 -4
  164. package/src/cli/commands/__tests__/report.test.ts +1 -1
  165. package/src/cli/commands/__tests__/scaffold.test.ts +4 -14
  166. package/src/cli/commands/__tests__/status-analysis-wiring.test.ts +3 -3
  167. package/src/cli/commands/__tests__/status-extra.test.ts +14 -14
  168. package/src/cli/commands/__tests__/status.test.ts +12 -12
  169. package/src/cli/commands/__tests__/sync-docs-agents.test.ts +1 -1
  170. package/src/cli/commands/check.ts +43 -82
  171. package/src/cli/commands/constraints-report.ts +4 -59
  172. package/src/cli/commands/constraints-retire.ts +49 -154
  173. package/src/cli/commands/constraints.ts +11 -26
  174. package/src/cli/commands/definitions.ts +2 -2
  175. package/src/cli/commands/init.ts +8 -179
  176. package/src/cli/commands/report.ts +19 -23
  177. package/src/cli/commands/scaffold-templates.ts +1 -37
  178. package/src/cli/commands/scaffold.ts +0 -11
  179. package/src/cli/commands/status.ts +10 -10
  180. package/src/cli/commands/sync-docs/agents-syncer.ts +4 -25
  181. package/src/core/CONTEXT.md +9 -9
  182. package/src/core/constraints/__tests__/capability-counts.test.ts +5 -5
  183. package/src/core/constraints/__tests__/collect-constraints.test.ts +13 -8
  184. package/src/core/constraints/__tests__/git-evidence.test.ts +4 -7
  185. package/src/core/constraints/__tests__/injection-writer.test.ts +8 -61
  186. package/src/core/constraints/__tests__/run-env.test.ts +5 -34
  187. package/src/core/constraints/__tests__/trace-injection.test.ts +1 -1
  188. package/src/core/constraints/capabilities-parser.ts +17 -5
  189. package/src/core/constraints/checker.ts +39 -88
  190. package/src/core/constraints/checkers/__tests__/check-outcome.test.ts +5 -8
  191. package/src/core/constraints/checkers/__tests__/governance-presence.test.ts +1 -53
  192. package/src/core/constraints/checkers/__tests__/iron-flags.test.ts +5 -25
  193. package/src/core/constraints/checkers/docs-freshness.ts +1 -1
  194. package/src/core/constraints/checkers/governance-presence.ts +4 -3
  195. package/src/core/constraints/checkers/index.ts +4 -10
  196. package/src/core/constraints/checkers/iron-flags.ts +3 -12
  197. package/src/core/constraints/checkers/no-test-simplification.ts +1 -1
  198. package/src/core/constraints/checkers/types.ts +1 -1
  199. package/src/core/constraints/definitions/guidelines.ts +8 -25
  200. package/src/core/constraints/definitions/iron-laws.ts +9 -82
  201. package/src/core/constraints/definitions.ts +14 -15
  202. package/src/core/constraints/index.ts +4 -19
  203. package/src/core/constraints/injection-writer.ts +16 -61
  204. package/src/core/constraints/run-env.ts +1 -33
  205. package/src/core/constraints/usage-report.ts +8 -15
  206. package/src/core/effective-constraints.ts +14 -45
  207. package/src/core/index.ts +3 -10
  208. package/src/core/project-config-loader.ts +20 -145
  209. package/src/core/validators/passes-gate.ts +6 -6
  210. package/src/failure/CONTEXT.md +1 -1
  211. package/src/hooks/__tests__/bootstrap.test.ts +3 -5
  212. package/src/index.ts +8 -18
  213. package/src/monitoring/__tests__/trace-file-anchoring.test.ts +1 -1
  214. package/src/monitoring/__tests__/traces.test.ts +22 -22
  215. package/src/monitoring/trace-analyzer.ts +12 -13
  216. package/src/monitoring/traces.ts +8 -8
  217. package/src/presets/__tests__/standard.test.ts +12 -16
  218. package/src/presets/standard.ts +14 -23
  219. package/src/types/__tests__/types.test.ts +3 -3
  220. package/src/types/constraint.ts +26 -40
  221. package/src/types/passes-gate.ts +5 -5
  222. package/src/types/project-config.ts +8 -77
  223. package/src/types/trace.ts +8 -11
  224. package/dist/core/constraints/agent-prompt-renderer.d.ts +0 -32
  225. package/dist/core/constraints/agent-prompt-renderer.d.ts.map +0 -1
  226. package/dist/core/constraints/agent-prompt-renderer.js +0 -55
  227. package/dist/core/constraints/agent-prompt-renderer.js.map +0 -1
  228. package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts +0 -6
  229. package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts.map +0 -1
  230. package/dist/core/constraints/checkers/no-bypass-checkpoint.js +0 -40
  231. package/dist/core/constraints/checkers/no-bypass-checkpoint.js.map +0 -1
  232. package/dist/core/constraints/definitions/prompts.d.ts +0 -12
  233. package/dist/core/constraints/definitions/prompts.d.ts.map +0 -1
  234. package/dist/core/constraints/definitions/prompts.js +0 -400
  235. package/dist/core/constraints/definitions/prompts.js.map +0 -1
  236. package/dist/core/constraints/injection-drift.d.ts +0 -61
  237. package/dist/core/constraints/injection-drift.d.ts.map +0 -1
  238. package/dist/core/constraints/injection-drift.js +0 -131
  239. package/dist/core/constraints/injection-drift.js.map +0 -1
  240. package/dist/core/constraints/injection-renderer.d.ts +0 -23
  241. package/dist/core/constraints/injection-renderer.d.ts.map +0 -1
  242. package/dist/core/constraints/injection-renderer.js +0 -44
  243. package/dist/core/constraints/injection-renderer.js.map +0 -1
  244. package/src/cli/commands/__tests__/check-drift.test.ts +0 -158
  245. package/src/cli/commands/__tests__/init-injection.test.ts +0 -466
  246. package/src/core/constraints/__tests__/agent-prompt-renderer.test.ts +0 -129
  247. package/src/core/constraints/__tests__/injection-drift.test.ts +0 -247
  248. package/src/core/constraints/agent-prompt-renderer.ts +0 -67
  249. package/src/core/constraints/checkers/__tests__/no-bypass-checkpoint.test.ts +0 -76
  250. package/src/core/constraints/checkers/no-bypass-checkpoint.ts +0 -40
  251. package/src/core/constraints/definitions/prompts.ts +0 -414
  252. package/src/core/constraints/injection-drift.ts +0 -142
  253. package/src/core/constraints/injection-renderer.ts +0 -44
@@ -39,28 +39,33 @@ describe('collectConstraints(收集模式,不抛)', () => {
39
39
 
40
40
  it('违规铁律如实进 ironLaws:satisfied=false 且 passed=false', async () => {
41
41
  const result = await checker.collectConstraints(VIOLATING);
42
- const violated = result.ironLaws.find((r: ConstraintResult) => r.id === 'no_completion_without_verification');
42
+ const violated = result.errors.find((r: ConstraintResult) => r.id === 'no_completion_without_verification');
43
43
  expect(violated).toBeDefined();
44
44
  expect(violated!.satisfied).toBe(false);
45
45
  expect(result.passed).toBe(false);
46
46
  });
47
47
 
48
48
  it('首个违规不截断:触发域内后续铁律照常评估', async () => {
49
- const result = await checker.collectConstraints(VIOLATING);
50
- const ids = result.ironLaws.map((r: ConstraintResult) => r.id);
51
- expect(ids).toContain('incremental_progress');
52
- expect(ids).toContain('no_implementation_without_requirement');
49
+ // 首条铁律(no_completion_without_verification)违规后,extraTriggers 带入的
50
+ // no_test_simplification 仍须出现在收集结果里
51
+ const result = await checker.collectConstraints({
52
+ ...VIOLATING,
53
+ extraTriggers: ['test_creation'],
54
+ });
55
+ const ids = result.errors.map((r: ConstraintResult) => r.id);
56
+ expect(ids).toContain('no_completion_without_verification');
57
+ expect(ids).toContain('no_test_simplification');
53
58
  });
54
59
 
55
60
  it('guidelines 照常执行,warningCount 与不满意条目同口径', async () => {
56
61
  const result = await checker.collectConstraints(VIOLATING);
57
- expect(result.guidelines.length).toBeGreaterThan(0);
58
- expect(result.warningCount).toBe(result.guidelines.filter((g: ConstraintResult) => !g.satisfied).length);
62
+ expect(result.warnings.length).toBeGreaterThan(0);
63
+ expect(result.warningCount).toBe(result.warnings.filter((g: ConstraintResult) => !g.satisfied).length);
59
64
  });
60
65
 
61
66
  it('干净上下文对照:passed=true、ironLaws 全满意', async () => {
62
67
  const result = await checker.collectConstraints(CLEAN);
63
68
  expect(result.passed).toBe(true);
64
- expect(result.ironLaws.every((r: ConstraintResult) => r.satisfied)).toBe(true);
69
+ expect(result.errors.every((r: ConstraintResult) => r.satisfied)).toBe(true);
65
70
  });
66
71
  });
@@ -22,7 +22,7 @@ import {
22
22
  } from '../git-evidence';
23
23
  import { buildConstraintContext } from '../context-builder';
24
24
  import { ConstraintChecker } from '../checker';
25
- import { GUIDELINES } from '../definitions';
25
+ import { CONSTRAINTS } from '../definitions';
26
26
  import type { MergedConstraintsConfig } from '../../../types/project-config';
27
27
 
28
28
  /** 建一个真 git fixture:committed src/existing.ts + 一个 staged 修改 */
@@ -181,10 +181,7 @@ describe('git 证据适配器(#87)', () => {
181
181
  const context = await buildConstraintContext({ projectPath: dir, staged: true, evidence });
182
182
  // capability_sync 经 CheckEnv.stagedDiffNames() 取同一份 git 证据
183
183
  const merged: MergedConstraintsConfig = {
184
- ironLaws: {},
185
- guidelines: { capability_sync: GUIDELINES['capability_sync'] },
186
- prompts: {},
187
- custom: [],
184
+ constraints: { capability_sync: CONSTRAINTS['capability_sync'] },
188
185
  disabled: [],
189
186
  unknownIds: [],
190
187
  };
@@ -193,8 +190,8 @@ describe('git 证据适配器(#87)', () => {
193
190
  const runResult = await checker.checkConstraints(context, merged, evidence);
194
191
 
195
192
  // capability_sync 确实被评估(非 skip)→ 它经 env.stagedDiffNames() 取过证据
196
- expect(runResult.guidelines.map(r => r.id)).toEqual(['capability_sync']);
197
- expect(runResult.guidelines[0].skipped).toBeUndefined();
193
+ expect(runResult.warnings.map(r => r.id)).toEqual(['capability_sync']);
194
+ expect(runResult.warnings[0].skipped).toBeUndefined();
198
195
  // 两个消费者都从注入的这一份实例取证据(checker 没有另起炉灶)
199
196
  expect(calls).toContain('context:changedFileNames');
200
197
  expect(calls).toContain('checker:changedFileNames');
@@ -1,32 +1,27 @@
1
1
  /**
2
- * injection-writer 旁测(架构评审候选1,ADR-0011
2
+ * injection-writer 旁测(架构评审候选1,ADR-0011;ADR-0029 收窄)
3
3
  *
4
- * 测试面 = 纯函数(字符串进、字符串出)+ 落点路由(真实 fs 临时目录)。
5
- * 幂等/半标记守护/两种尾部形状/读写路由优先级全部在此测一次;
6
- * 消费方(init/retire/drift)只测各自语义(init-injection.test 行为面)。
4
+ * 测试面 = 纯函数(字符串进、字符串出)+ 治理正本探测。
5
+ * 幂等/半标记守护/两种尾部形状在此测一次。
6
+ * ADR-0029:注入段落点路由(resolveInjectionTarget/resolveGovernanceLanding)
7
+ * 已随文本注入层关停删除,相关用例移除。
7
8
  */
8
9
 
9
- import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
10
- import * as fs from 'fs';
11
- import * as path from 'path';
10
+ import { describe, it, expect } from '@jest/globals';
12
11
  import {
13
12
  replaceStandaloneRange,
14
13
  replaceEnclosedRange,
15
14
  cutMarkerBlock,
16
- resolveInjectionTarget,
17
- resolveGovernanceLanding,
18
15
  GOVERNANCE_HEADING,
19
16
  hasGovernanceContract,
20
17
  countGovernanceHeadings,
21
18
  hasPreserveBlock,
22
19
  } from '../injection-writer';
23
- import {
24
- CONSTRAINTS_START_MARKER as CS,
25
- CONSTRAINTS_END_MARKER as CE,
26
- } from '../injection-renderer';
27
20
 
28
21
  const B = '<!-- B -->';
29
22
  const E = '<!-- E -->';
23
+ const CS = '<!-- CS -->';
24
+ const CE = '<!-- CE -->';
30
25
 
31
26
  describe('replaceStandaloneRange — 独立成节形状', () => {
32
27
  it('替换含标记区间;尾文多换行折叠为恰好一个空行', () => {
@@ -97,54 +92,6 @@ describe('cutMarkerBlock', () => {
97
92
  });
98
93
  });
99
94
 
100
- describe('落点路由(读写两侧,studio #307/#302)', () => {
101
- let dir: string;
102
-
103
- beforeEach(() => {
104
- dir = fs.mkdtempSync(path.join(process.cwd(), 'temp-test-inj-writer-'));
105
- });
106
- afterEach(() => fs.rmSync(dir, { recursive: true, force: true }));
107
-
108
- const write = (name: string, content: string) =>
109
- fs.writeFileSync(path.join(dir, name), content, 'utf-8');
110
-
111
- it('resolveInjectionTarget:CLAUDE.md 完整标记段优先于 AGENTS.md', () => {
112
- write('CLAUDE.md', `x\n${CS}\nbody\n${CE}\n`);
113
- write('AGENTS.md', `<!-- PRESERVE:governance -->\n${CS}\nbody2\n${CE}\n`);
114
- expect(resolveInjectionTarget(dir)?.file).toBe('CLAUDE.md');
115
- });
116
-
117
- it('CLAUDE.md 标记残缺(单边)不算落点 → 落 AGENTS.md', () => {
118
- write('CLAUDE.md', `x\n${CS}\nbroken\n`);
119
- write('AGENTS.md', `${CS}\nbody\n${CE}\n`);
120
- expect(resolveInjectionTarget(dir)?.file).toBe('AGENTS.md');
121
- });
122
-
123
- it('两处均无完整标记段 → null(未注入)', () => {
124
- write('CLAUDE.md', '# 无约束标记\n');
125
- expect(resolveInjectionTarget(dir)).toBeNull();
126
- });
127
-
128
- it('resolveGovernanceLanding:CLAUDE.md 有标记或有旧版 Governance Rules 块 → claude-md', () => {
129
- write('CLAUDE.md', `${CS}\nbody\n${CE}\n`);
130
- expect(resolveGovernanceLanding(dir).target).toBe('claude-md');
131
- write('CLAUDE.md', '# CLAUDE.md\n\n## Governance Rules\n\n手写\n');
132
- expect(resolveGovernanceLanding(dir).target).toBe('claude-md');
133
- });
134
-
135
- it('CLAUDE.md 与治理无关 / 不存在 → agents-md', () => {
136
- write('CLAUDE.md', '# CLAUDE.md\n\n@AGENTS.md\n');
137
- expect(resolveGovernanceLanding(dir).target).toBe('agents-md');
138
- fs.rmSync(path.join(dir, 'CLAUDE.md'));
139
- expect(resolveGovernanceLanding(dir).target).toBe('agents-md');
140
- });
141
-
142
- it('落点路由消费共享宽松谓词:双空格标题变体也路由 claude-md(fail-open)', () => {
143
- write('CLAUDE.md', '# CLAUDE.md\n\n## Governance Rules\n\n手写\n');
144
- expect(resolveGovernanceLanding(dir).target).toBe('claude-md');
145
- });
146
- });
147
-
148
95
  describe('治理契约探测共享符号(#83,ADR-0011 补注:收口范围含探测器)', () => {
149
96
  it('GOVERNANCE_HEADING 是标题字面量单一来源', () => {
150
97
  expect(GOVERNANCE_HEADING).toBe('## Governance Rules');
@@ -47,7 +47,7 @@ function writeTraces(projectPath: string, lines: string[]): void {
47
47
  }
48
48
 
49
49
  const traceLine = (id: string, result: 'pass' | 'fail'): string =>
50
- JSON.stringify({ constraintId: id, level: 'iron_law', timestamp: 1, result });
50
+ JSON.stringify({ constraintId: id, severity: 'error', timestamp: 1, result });
51
51
 
52
52
  const CORRUPT = '{"constraintId":"broken"';
53
53
 
@@ -125,18 +125,11 @@ describe('createRunEnv', () => {
125
125
  });
126
126
  });
127
127
 
128
- describe('配置一次装载 — rawConfig / customConstraints(ADR-0023 决策 2)', () => {
128
+ describe('配置一次装载 — rawConfig(ADR-0023 决策 2)', () => {
129
129
  let dir: string;
130
130
 
131
131
  const writeConfig = (content: string) => writeProjectConfig(dir, content);
132
132
 
133
- /** 落 `.harness/<fileName>`(夹具可能还没有 .harness 目录,先补上) */
134
- const writeHarnessFile = (fileName: string, body: string) => {
135
- const target = path.join(dir, '.harness', fileName);
136
- fs.mkdirSync(path.dirname(target), { recursive: true });
137
- fs.writeFileSync(target, body, 'utf-8');
138
- };
139
-
140
133
  beforeEach(() => {
141
134
  dir = createProjectFixture({ name: 'run-env-config' });
142
135
  });
@@ -191,27 +184,6 @@ describe('配置一次装载 — rawConfig / customConstraints(ADR-0023 决策
191
184
  expect(resolveRunEnv().projectPath).toBe(process.cwd());
192
185
  });
193
186
 
194
- it('customConstraints 取 custom_constraints 段,run 内同名文件至多读一次', () => {
195
- const write = (body: string) => writeHarnessFile('custom-constraints.yml', body);
196
- write('custom_constraints:\n a:\n level: iron_law\n rule: 只此一份\n');
197
- const env = createRunEnv(dir);
198
- expect(Object.keys(env.customConstraints('custom-constraints.yml'))).toEqual(['a']);
199
-
200
- write('custom_constraints:\n b:\n level: guideline\n rule: 后来的\n');
201
- expect(Object.keys(env.customConstraints('custom-constraints.yml'))).toEqual(['a']);
202
- });
203
-
204
- it('customConstraints:文件缺失 = {};不同文件名各自 memo', () => {
205
- const env = createRunEnv(dir);
206
- expect(env.customConstraints('missing.yml')).toEqual({});
207
-
208
- writeHarnessFile(
209
- 'other.yml',
210
- 'custom_constraints:\n c:\n level: guideline\n rule: r\n'
211
- );
212
- expect(Object.keys(env.customConstraints('other.yml'))).toEqual(['c']);
213
- expect(env.customConstraints('missing.yml')).toEqual({});
214
- });
215
187
  });
216
188
 
217
189
  describe('context-builder 经注入的观察面取证据', () => {
@@ -235,7 +207,6 @@ describe('context-builder 经注入的观察面取证据', () => {
235
207
  },
236
208
  sourceRoots: () => ['src'],
237
209
  rawConfig: () => undefined,
238
- customConstraints: () => ({}),
239
210
  capabilities: () => undefined,
240
211
  };
241
212
  return { env, limits };
@@ -251,8 +222,8 @@ describe('context-builder 经注入的观察面取证据', () => {
251
222
 
252
223
  it('hasFailingTest / hasVerificationEvidence 各按自己的窗口向 env 取数,不另开读', async () => {
253
224
  const { env, limits } = countingEnv([
254
- { constraintId: 'p', level: 'iron_law', timestamp: 1, result: 'pass' },
255
- { constraintId: 'f', level: 'iron_law', timestamp: 2, result: 'fail' },
225
+ { constraintId: 'p', severity: 'error', timestamp: 1, result: 'pass' },
226
+ { constraintId: 'f', severity: 'error', timestamp: 2, result: 'fail' },
256
227
  ]);
257
228
  const ctx = await buildConstraintContext({
258
229
  projectPath: dir,
@@ -268,7 +239,7 @@ describe('context-builder 经注入的观察面取证据', () => {
268
239
 
269
240
  it('窗口里没有 pass 时验证证据为 false(合并读取不改判定)', async () => {
270
241
  const { env } = countingEnv([
271
- { constraintId: 'f', level: 'iron_law', timestamp: 2, result: 'fail' },
242
+ { constraintId: 'f', severity: 'error', timestamp: 2, result: 'fail' },
272
243
  ]);
273
244
  const ctx = await buildConstraintContext({
274
245
  projectPath: dir,
@@ -51,7 +51,7 @@ describe('trace 记录器构造注入(harness#88)', () => {
51
51
  await checker.checkConstraints(context());
52
52
 
53
53
  expect(records.map(r => r.constraintId)).toEqual(
54
- expect.arrayContaining(['incremental_progress', 'no_implementation_without_requirement'])
54
+ expect.arrayContaining(['no_completion_without_verification', 'no_hardcoded_credentials'])
55
55
  );
56
56
  expect(records.every(r => ['pass', 'fail', 'skip'].includes(r.result))).toBe(true);
57
57
  });
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import * as fs from 'fs';
13
- import { IRON_LAWS, GUIDELINES } from './definitions';
13
+ import { CONSTRAINTS } from './definitions';
14
14
  import { FreshnessRunner } from './doc-freshness/runner';
15
15
  import type { DocFreshnessCheck } from '../../types/project-config';
16
16
 
@@ -79,10 +79,14 @@ export function readCapabilitiesEntries(capabilitiesPath: string, options: Capab
79
79
  * checker 与 sync-docs 都应按此跳过条目级比对。
80
80
  */
81
81
  export function isCapabilityListingFormat(content: string): boolean {
82
- // 能力清单格式特征:包含 "CLI Commands (N)" / "Iron Laws (N)" 等计数行
82
+ // 能力清单格式特征:包含 "CLI Commands (N)" 与约束计数行
83
+ // (ADR-0029 前为 "Iron Laws (N)" / "Guidelines (N)",现行为 "errors (N)" / "warnings (N)",
84
+ // 新旧行都认——旧文档不因此失去格式身份)
83
85
  return /CLI Commands\s*\(\d+\)/.test(content) ||
84
86
  /Iron Laws?\s*\(\d+\)/.test(content) ||
85
- /Guidelines?\s*\(\d+\)/.test(content);
87
+ /Guidelines?\s*\(\d+\)/.test(content) ||
88
+ /errors?\s*\(\d+\)/.test(content) ||
89
+ /warnings?\s*\(\d+\)/.test(content);
86
90
  }
87
91
 
88
92
  /**
@@ -143,8 +147,16 @@ function capabilityCountRules(source: CapabilityDefinitionSource): CapabilityCou
143
147
  actual: source.commands.length + source.gates.filter(g => g.cli).length,
144
148
  },
145
149
  { label: 'Quality Gates', pattern: 'Quality Gates?\\s*\\((\\d+)\\)', actual: source.gates.length },
146
- { label: 'Iron Laws', pattern: 'Iron Laws?\\s*\\((\\d+)\\)', actual: Object.keys(IRON_LAWS).length },
147
- { label: 'Guidelines', pattern: 'Guidelines?\\s*\\((\\d+)\\)', actual: Object.keys(GUIDELINES).length },
150
+ {
151
+ label: 'errors',
152
+ pattern: 'errors?\\s*\\((\\d+)\\)',
153
+ actual: Object.values(CONSTRAINTS).filter(c => c.severity === 'error').length,
154
+ },
155
+ {
156
+ label: 'warnings',
157
+ pattern: 'warnings?\\s*\\((\\d+)\\)',
158
+ actual: Object.values(CONSTRAINTS).filter(c => c.severity === 'warning').length,
159
+ },
148
160
  ];
149
161
  }
150
162
 
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * 约束检查引擎
3
3
  *
4
- * kind 二元模型(ADR-0001):
5
- * - check · Iron Laws:检查失败立即抛出异常
6
- * - check · Guidelines:检查失败记录警告
7
- * - prompt:不执行 checker,仅参与注入
4
+ * severity 显式模型(ADR-0029):
5
+ * - severity='error':检查失败立即抛出异常(block 模式)
6
+ * - severity='warning':检查失败记录警告
7
+ * 全部约束 kind='check',必须带真实 checker(注册表闭环)。
8
8
  */
9
9
 
10
10
  import {
@@ -12,11 +12,10 @@ import {
12
12
  ConstraintContext,
13
13
  ConstraintResult,
14
14
  ConstraintCheckResult,
15
- ConstraintLevel,
16
15
  ConstraintViolationError,
17
16
  } from '../../types/constraint';
18
17
  import type { ExecutionTrace } from '../../types/trace';
19
- import { IRON_LAWS, GUIDELINES, PROMPTS } from './definitions';
18
+ import { CONSTRAINTS } from './definitions';
20
19
  import type { MergedConstraintsConfig } from '../../types/project-config';
21
20
  import { matchesTrigger } from './triggers';
22
21
  import { join, relative } from 'path';
@@ -74,21 +73,8 @@ export class ConstraintChecker {
74
73
  *
75
74
  * @param customConfig 可选,per-request 自定义配置;不传则返回内置约束集
76
75
  */
77
- getConstraints(customConfig?: MergedConstraintsConfig | null): {
78
- ironLaws: Record<string, Constraint>;
79
- guidelines: Record<string, Constraint>;
80
- prompts: Record<string, Constraint>;
81
- } {
82
- const config = customConfig;
83
- const source = config
84
- ? { ironLaws: config.ironLaws, guidelines: config.guidelines, prompts: config.prompts ?? PROMPTS }
85
- : { ironLaws: IRON_LAWS, guidelines: GUIDELINES, prompts: PROMPTS };
86
-
87
- return {
88
- ironLaws: source.ironLaws,
89
- guidelines: source.guidelines,
90
- prompts: source.prompts,
91
- };
76
+ getConstraints(customConfig?: MergedConstraintsConfig | null): Record<string, Constraint> {
77
+ return customConfig ? customConfig.constraints : CONSTRAINTS;
92
78
  }
93
79
 
94
80
  /**
@@ -103,17 +89,6 @@ export class ConstraintChecker {
103
89
  evidence?: GitEvidence,
104
90
  runEnv?: RunEnv
105
91
  ): Promise<ConstraintResult> {
106
- // prompt 类约束不参与 checker 执行(ADR-0001:仅参与注入)
107
- if (constraint.kind === 'prompt') {
108
- return {
109
- id: constraint.id,
110
- level: constraint.level,
111
- satisfied: true,
112
- constraint,
113
- checkedAt: new Date(),
114
- };
115
- }
116
-
117
92
  // 检查前置条件('skip' = 约定未采用/证据未接线:satisfied 置 true 但不计 pass/fail)
118
93
  const outcome = normalizeCheckOutcome(
119
94
  await this.checkPrecondition(constraint, context, evidence, runEnv)
@@ -122,7 +97,7 @@ export class ConstraintChecker {
122
97
  if (outcome.skipped) {
123
98
  return {
124
99
  id: constraint.id,
125
- level: constraint.level,
100
+ severity: constraint.severity,
126
101
  satisfied: true,
127
102
  skipped: true,
128
103
  constraint,
@@ -135,7 +110,7 @@ export class ConstraintChecker {
135
110
 
136
111
  return {
137
112
  id: constraint.id,
138
- level: constraint.level,
113
+ severity: constraint.severity,
139
114
  satisfied,
140
115
  constraint,
141
116
  message: satisfied ? undefined : constraint.message,
@@ -145,22 +120,6 @@ export class ConstraintChecker {
145
120
  };
146
121
  }
147
122
 
148
- /**
149
- * 根据约束层级获取严重性
150
- */
151
- private getSeverity(level: ConstraintLevel): 'error' | 'warning' | 'info' {
152
- switch (level) {
153
- case 'iron_law':
154
- return 'error';
155
- case 'guideline':
156
- return 'warning';
157
- case 'prompt':
158
- return 'info';
159
- default:
160
- return 'warning';
161
- }
162
- }
163
-
164
123
  /**
165
124
  * 记录约束检查的 trace
166
125
  */
@@ -171,11 +130,10 @@ export class ConstraintChecker {
171
130
  ): void {
172
131
  this.traceRecorder.record({
173
132
  constraintId: constraint.id,
174
- level: constraint.level,
133
+ severity: constraint.severity,
175
134
  timestamp: Date.now(),
176
135
  result: checkResult.skipped ? 'skip' : checkResult.satisfied ? 'pass' : 'fail',
177
136
  operation: context.operation,
178
- severity: this.getSeverity(constraint.level),
179
137
  projectPath: context.projectPath,
180
138
  sessionId: context.sessionId,
181
139
  evidence: checkResult.evidence,
@@ -186,7 +144,7 @@ export class ConstraintChecker {
186
144
  * 检查约束前置条件(工单 21:分发至 checkers/ 注册表)
187
145
  *
188
146
  * 注册表闭环(ADR-0001):kind='check' 未注册 checker 直接抛错,
189
- * 不再有"未注册默认通过"路径;kind='prompt' 在 check() 入口已短路。
147
+ * 不再有"未注册默认通过"路径。
190
148
  *
191
149
  * git 证据(stagedDiff/stagedDiffNames)单一来源 = GitEvidence adapter(#87):
192
150
  * 一次 run 内调用方传同一实例即至多取证一次,run 外调用独占一份。
@@ -202,7 +160,7 @@ export class ConstraintChecker {
202
160
  if (!impl) {
203
161
  throw new Error(
204
162
  `[harness] 约束 "${constraint.id}" (kind='check') 未注册 checker,拒绝静默通过。` +
205
- `请在 checkers/ 注册实现,或将约束改为 kind='prompt'。`
163
+ `请在 checkers/ 注册实现(纯文本提示层已随 ADR-0029 关停,文本规则写入项目治理文档)。`
206
164
  );
207
165
  }
208
166
 
@@ -232,31 +190,27 @@ export class ConstraintChecker {
232
190
  context: ConstraintContext,
233
191
  customConfig?: MergedConstraintsConfig | null
234
192
  ): {
235
- ironLaws: Constraint[];
236
- guidelines: Constraint[];
237
- prompts: Constraint[];
193
+ errors: Constraint[];
194
+ warnings: Constraint[];
238
195
  } {
239
196
  const operations = [context.operation, ...(context.extraTriggers ?? [])];
240
197
  const constraints = this.getConstraints(customConfig);
241
198
 
242
- const filterByTrigger = (constraintSet: Record<string, Constraint>): Constraint[] => {
243
- return Object.values(constraintSet).filter(constraint =>
244
- matchesTrigger(constraint, operations)
245
- );
246
- };
199
+ const applicable = Object.values(constraints).filter(constraint =>
200
+ matchesTrigger(constraint, operations)
201
+ );
247
202
 
248
203
  return {
249
- ironLaws: filterByTrigger(constraints.ironLaws),
250
- guidelines: filterByTrigger(constraints.guidelines),
251
- prompts: filterByTrigger(constraints.prompts),
204
+ errors: applicable.filter(c => c.severity === 'error'),
205
+ warnings: applicable.filter(c => c.severity === 'warning'),
252
206
  };
253
207
  }
254
208
 
255
209
  /**
256
210
  * 执行约束检查
257
211
  *
258
- * - Iron Laws:检查失败立即抛出异常
259
- * - Guidelines:检查失败记录警告
212
+ * - severity='error':检查失败立即抛出异常
213
+ * - severity='warning':检查失败记录警告
260
214
  *
261
215
  * @param context 约束上下文
262
216
  * @param customConfig 可选,per-request 自定义配置(避免多请求间的单例状态污染)
@@ -279,7 +233,7 @@ export class ConstraintChecker {
279
233
  * 收集模式执行约束检查(harness report 的不抛出口,架构评审候选1)
280
234
  *
281
235
  * 与 checkConstraints 共享同一检查体,唯一差别是不 throw:
282
- * 铁律违规照进 result.ironLaws、passed=false,后续铁律与 guidelines 照常执行,
236
+ * error 级违规照进 result.errors、passed=false,后续 error 与 warning 级照常执行,
283
237
  * trace 逐条照记。报告类消费者拿全量视图;阻断语义只属于 checkConstraints
284
238
  * (throw 契约是 #119 判定证据的外溢面,逐字不动)。
285
239
  */
@@ -294,7 +248,7 @@ export class ConstraintChecker {
294
248
 
295
249
  /**
296
250
  * checkConstraints / collectConstraints 的共享检查体;
297
- * mode='block' 首个铁律违规即抛,mode='collect' 全量跑完不抛
251
+ * mode='block' 首个 error 级违规即抛,mode='collect' 全量跑完不抛
298
252
  */
299
253
  private async runAllConstraints(
300
254
  context: ConstraintContext,
@@ -311,8 +265,8 @@ export class ConstraintChecker {
311
265
  const env = runEnv ?? createRunEnv(projectPath);
312
266
 
313
267
  const result: ConstraintCheckResult = {
314
- ironLaws: [],
315
- guidelines: [],
268
+ errors: [],
269
+ warnings: [],
316
270
  passed: true,
317
271
  warningCount: 0,
318
272
  };
@@ -321,12 +275,12 @@ export class ConstraintChecker {
321
275
  // context.operation 为主触发条件,extraTriggers 为次级推断(ADR-0001),任一命中即匹配
322
276
  const operations = [context.operation, ...(context.extraTriggers ?? [])];
323
277
 
324
- // 1. Iron Laws: block 模式首个违规即抛;collect 模式全量收集
325
- for (const constraint of Object.values(constraints.ironLaws)) {
278
+ // 1. error 级: block 模式首个违规即抛;collect 模式全量收集
279
+ for (const constraint of Object.values(constraints).filter(c => c.severity === 'error')) {
326
280
  if (!matchesTrigger(constraint, operations)) continue;
327
281
 
328
282
  const checkResult = await this.check(constraint, context, run, env);
329
- result.ironLaws.push(checkResult);
283
+ result.errors.push(checkResult);
330
284
  this.recordTrace(constraint, checkResult, context);
331
285
 
332
286
  if (!checkResult.satisfied) {
@@ -337,12 +291,12 @@ export class ConstraintChecker {
337
291
  }
338
292
  }
339
293
 
340
- // 2. Guidelines: 记录警告
341
- for (const constraint of Object.values(constraints.guidelines)) {
294
+ // 2. warning 级: 记录警告
295
+ for (const constraint of Object.values(constraints).filter(c => c.severity === 'warning')) {
342
296
  if (!matchesTrigger(constraint, operations)) continue;
343
297
 
344
298
  const checkResult = await this.check(constraint, context, run, env);
345
- result.guidelines.push(checkResult);
299
+ result.warnings.push(checkResult);
346
300
  this.recordTrace(constraint, checkResult, context);
347
301
 
348
302
  if (!checkResult.satisfied) {
@@ -354,12 +308,12 @@ export class ConstraintChecker {
354
308
  }
355
309
 
356
310
  /**
357
- * 执行前检查(仅检查 Iron Laws)
311
+ * 执行前检查(仅检查 severity='error' 的约束)
358
312
  *
359
313
  * @param context 约束上下文
360
314
  * @param customConfig 可选,per-request 自定义配置(避免多请求间的单例状态污染)
361
315
  * @param evidence 可选,本次检查共用的 git 证据 adapter(#87,同 checkConstraints)
362
- * @throws ConstraintViolationError 如果有铁律违规
316
+ * @throws ConstraintViolationError 如果有 error 级违规
363
317
  */
364
318
  async beforeExecution(
365
319
  context: ConstraintContext,
@@ -373,7 +327,7 @@ export class ConstraintChecker {
373
327
  const constraints = this.getConstraints(customConfig);
374
328
  const operations = [context.operation, ...(context.extraTriggers ?? [])];
375
329
 
376
- for (const constraint of Object.values(constraints.ironLaws)) {
330
+ for (const constraint of Object.values(constraints).filter(c => c.severity === 'error')) {
377
331
  if (!matchesTrigger(constraint, operations)) continue;
378
332
 
379
333
  const result = await this.check(constraint, context, run, env);
@@ -401,15 +355,12 @@ export async function checkConstraint(
401
355
  const checker = ConstraintChecker.getInstance();
402
356
  const constraints = checker.getConstraints(customConfig);
403
357
 
404
- const constraint =
405
- constraints.ironLaws[constraintId] ||
406
- constraints.guidelines[constraintId] ||
407
- constraints.prompts[constraintId];
358
+ const constraint = constraints[constraintId];
408
359
 
409
360
  if (!constraint) {
410
361
  return {
411
362
  id: constraintId,
412
- level: 'guideline',
363
+ severity: 'warning',
413
364
  satisfied: false,
414
365
  message: `未知的约束: ${constraintId}`,
415
366
  checkedAt: new Date(),
@@ -430,7 +381,7 @@ export interface CheckConstraintsOptions {
430
381
  }
431
382
 
432
383
  /**
433
- * 快捷函数:执行三层检查
384
+ * 快捷函数:执行约束检查
434
385
  *
435
386
  * @param context 约束上下文
436
387
  * @param options.onTrace 每条约束检查后的回调(用于记录 trace 到外部存储)
@@ -442,8 +393,8 @@ export async function checkConstraints(
442
393
  ): Promise<ConstraintCheckResult> {
443
394
  const result = await ConstraintChecker.getInstance().checkConstraints(context, options?.customConfig ?? null);
444
395
  if (options?.onTrace) {
445
- for (const r of result.ironLaws) options.onTrace(r);
446
- for (const r of result.guidelines) options.onTrace(r);
396
+ for (const r of result.errors) options.onTrace(r);
397
+ for (const r of result.warnings) options.onTrace(r);
447
398
  }
448
399
  return result;
449
400
  }
@@ -23,7 +23,7 @@ import type { MergedConstraintsConfig } from '../../../../types/project-config';
23
23
  const CAPABILITY_SYNC: Constraint = {
24
24
  id: 'capability_sync',
25
25
  kind: 'check',
26
- level: 'guideline',
26
+ severity: 'warning',
27
27
  rule: 'CODE CHANGES MUST UPDATE CAPABILITIES.MD',
28
28
  message: '核心模块变更必须同步功能清单',
29
29
  trigger: ['module_modification'],
@@ -62,11 +62,8 @@ describe('normalizeCheckOutcome — 三态 + 证据归一', () => {
62
62
  /** 只含 capability_sync 的生效集:一次 run 一条 trace,不牵动其他约束 */
63
63
  function onlyCapabilitySync(): MergedConstraintsConfig {
64
64
  return {
65
- ironLaws: {},
66
- guidelines: { capability_sync: CAPABILITY_SYNC },
67
- prompts: {},
65
+ constraints: { capability_sync: CAPABILITY_SYNC },
68
66
  disabled: [],
69
- custom: [],
70
67
  };
71
68
  }
72
69
 
@@ -81,7 +78,7 @@ async function runGuideline(dir: string): Promise<{
81
78
  { operation: 'module_modification', projectPath: dir },
82
79
  onlyCapabilitySync()
83
80
  );
84
- const result = run.guidelines.find(r => r.id === 'capability_sync')!;
81
+ const result = run.warnings.find(r => r.id === 'capability_sync')!;
85
82
  const trace = traces.find(t => t.constraintId === 'capability_sync')!;
86
83
  return { result, trace };
87
84
  }
@@ -151,7 +148,7 @@ describe('证据随铁律异常外溢(CLI catch 分支只打印 error.message
151
148
  it('ConstraintViolationError 文案带出证据行', () => {
152
149
  const error = new ConstraintViolationError({
153
150
  id: 'docs_freshness',
154
- level: 'iron_law',
151
+ severity: 'error',
155
152
  satisfied: false,
156
153
  message: '文档新鲜度检查未通过',
157
154
  evidence: ['CAPABILITIES.md 登记的条目不存在:', 'src/gone.ts'],
@@ -165,7 +162,7 @@ describe('证据随铁律异常外溢(CLI catch 分支只打印 error.message
165
162
  it('无证据时文案保持原样(旧消费方断言不受影响)', () => {
166
163
  const error = new ConstraintViolationError({
167
164
  id: 'no_test_simplification',
168
- level: 'iron_law',
165
+ severity: 'error',
169
166
  satisfied: false,
170
167
  message: '禁止简化测试绕过困难',
171
168
  checkedAt: new Date(),