@dommaker/harness 1.8.1 → 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 (299) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +10 -13
  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/cli/commands/sync-docs/capabilities-syncer.d.ts +22 -0
  42. package/dist/cli/commands/sync-docs/capabilities-syncer.d.ts.map +1 -1
  43. package/dist/cli/commands/sync-docs/capabilities-syncer.js +113 -8
  44. package/dist/cli/commands/sync-docs/capabilities-syncer.js.map +1 -1
  45. package/dist/cli/commands/sync-docs/index.d.ts.map +1 -1
  46. package/dist/cli/commands/sync-docs/index.js +36 -4
  47. package/dist/cli/commands/sync-docs/index.js.map +1 -1
  48. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  49. package/dist/core/constraints/capabilities-parser.js +16 -4
  50. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  51. package/dist/core/constraints/checker.d.ts +15 -24
  52. package/dist/core/constraints/checker.d.ts.map +1 -1
  53. package/dist/core/constraints/checker.js +33 -72
  54. package/dist/core/constraints/checker.js.map +1 -1
  55. package/dist/core/constraints/checkers/docs-freshness.js +1 -1
  56. package/dist/core/constraints/checkers/docs-freshness.js.map +1 -1
  57. package/dist/core/constraints/checkers/governance-presence.d.ts +2 -1
  58. package/dist/core/constraints/checkers/governance-presence.d.ts.map +1 -1
  59. package/dist/core/constraints/checkers/governance-presence.js +4 -3
  60. package/dist/core/constraints/checkers/governance-presence.js.map +1 -1
  61. package/dist/core/constraints/checkers/index.d.ts +1 -1
  62. package/dist/core/constraints/checkers/index.d.ts.map +1 -1
  63. package/dist/core/constraints/checkers/index.js +4 -8
  64. package/dist/core/constraints/checkers/index.js.map +1 -1
  65. package/dist/core/constraints/checkers/iron-flags.d.ts +3 -4
  66. package/dist/core/constraints/checkers/iron-flags.d.ts.map +1 -1
  67. package/dist/core/constraints/checkers/iron-flags.js +4 -5
  68. package/dist/core/constraints/checkers/iron-flags.js.map +1 -1
  69. package/dist/core/constraints/checkers/no-test-simplification.js +1 -1
  70. package/dist/core/constraints/checkers/no-test-simplification.js.map +1 -1
  71. package/dist/core/constraints/checkers/types.d.ts +1 -1
  72. package/dist/core/constraints/checkers/types.js +1 -1
  73. package/dist/core/constraints/definitions/guidelines.d.ts +4 -4
  74. package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -1
  75. package/dist/core/constraints/definitions/guidelines.js +9 -25
  76. package/dist/core/constraints/definitions/guidelines.js.map +1 -1
  77. package/dist/core/constraints/definitions/iron-laws.d.ts +4 -4
  78. package/dist/core/constraints/definitions/iron-laws.d.ts.map +1 -1
  79. package/dist/core/constraints/definitions/iron-laws.js +10 -81
  80. package/dist/core/constraints/definitions/iron-laws.js.map +1 -1
  81. package/dist/core/constraints/definitions.d.ts +7 -9
  82. package/dist/core/constraints/definitions.d.ts.map +1 -1
  83. package/dist/core/constraints/definitions.js +13 -16
  84. package/dist/core/constraints/definitions.js.map +1 -1
  85. package/dist/core/constraints/index.d.ts +2 -5
  86. package/dist/core/constraints/index.d.ts.map +1 -1
  87. package/dist/core/constraints/index.js +3 -13
  88. package/dist/core/constraints/index.js.map +1 -1
  89. package/dist/core/constraints/injection-writer.d.ts +10 -38
  90. package/dist/core/constraints/injection-writer.d.ts.map +1 -1
  91. package/dist/core/constraints/injection-writer.js +17 -54
  92. package/dist/core/constraints/injection-writer.js.map +1 -1
  93. package/dist/core/constraints/run-env.d.ts +1 -10
  94. package/dist/core/constraints/run-env.d.ts.map +1 -1
  95. package/dist/core/constraints/run-env.js +1 -22
  96. package/dist/core/constraints/run-env.js.map +1 -1
  97. package/dist/core/constraints/usage-report.d.ts +5 -7
  98. package/dist/core/constraints/usage-report.d.ts.map +1 -1
  99. package/dist/core/constraints/usage-report.js +5 -10
  100. package/dist/core/constraints/usage-report.js.map +1 -1
  101. package/dist/core/effective-constraints.d.ts +12 -22
  102. package/dist/core/effective-constraints.d.ts.map +1 -1
  103. package/dist/core/effective-constraints.js +13 -30
  104. package/dist/core/effective-constraints.js.map +1 -1
  105. package/dist/core/index.d.ts +2 -2
  106. package/dist/core/index.d.ts.map +1 -1
  107. package/dist/core/index.js +3 -9
  108. package/dist/core/index.js.map +1 -1
  109. package/dist/core/project-config-loader.d.ts +4 -42
  110. package/dist/core/project-config-loader.d.ts.map +1 -1
  111. package/dist/core/project-config-loader.js +16 -125
  112. package/dist/core/project-config-loader.js.map +1 -1
  113. package/dist/core/validators/passes-gate.d.ts +2 -2
  114. package/dist/core/validators/passes-gate.js +6 -6
  115. package/dist/core/validators/passes-gate.js.map +1 -1
  116. package/dist/hooks/bootstrap.d.ts +9 -12
  117. package/dist/hooks/bootstrap.d.ts.map +1 -1
  118. package/dist/hooks/bootstrap.js +9 -31
  119. package/dist/hooks/bootstrap.js.map +1 -1
  120. package/dist/hooks/index.d.ts +5 -7
  121. package/dist/hooks/index.d.ts.map +1 -1
  122. package/dist/hooks/index.js +4 -10
  123. package/dist/hooks/index.js.map +1 -1
  124. package/dist/index.d.ts +9 -12
  125. package/dist/index.d.ts.map +1 -1
  126. package/dist/index.js +10 -23
  127. package/dist/index.js.map +1 -1
  128. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  129. package/dist/monitoring/trace-analyzer.js +11 -12
  130. package/dist/monitoring/trace-analyzer.js.map +1 -1
  131. package/dist/monitoring/traces.d.ts +4 -4
  132. package/dist/monitoring/traces.d.ts.map +1 -1
  133. package/dist/monitoring/traces.js +8 -8
  134. package/dist/monitoring/traces.js.map +1 -1
  135. package/dist/presets/standard.d.ts +8 -10
  136. package/dist/presets/standard.d.ts.map +1 -1
  137. package/dist/presets/standard.js +10 -16
  138. package/dist/presets/standard.js.map +1 -1
  139. package/dist/types/constraint.d.ts +24 -35
  140. package/dist/types/constraint.d.ts.map +1 -1
  141. package/dist/types/constraint.js +8 -7
  142. package/dist/types/constraint.js.map +1 -1
  143. package/dist/types/passes-gate.d.ts +5 -5
  144. package/dist/types/passes-gate.d.ts.map +1 -1
  145. package/dist/types/project-config.d.ts +8 -66
  146. package/dist/types/project-config.d.ts.map +1 -1
  147. package/dist/types/project-config.js +3 -2
  148. package/dist/types/project-config.js.map +1 -1
  149. package/dist/types/trace.d.ts +8 -10
  150. package/dist/types/trace.d.ts.map +1 -1
  151. package/package.json +2 -2
  152. package/src/CONTEXT.md +3 -3
  153. package/src/__tests__/checker-extra.test.ts +37 -61
  154. package/src/__tests__/checker.test.ts +10 -115
  155. package/src/__tests__/effective-constraints.test.ts +18 -83
  156. package/src/__tests__/iron-laws.test.ts +71 -90
  157. package/src/__tests__/passes-gate-check.test.ts +2 -2
  158. package/src/__tests__/project-config-loader-extra.test.ts +22 -123
  159. package/src/__tests__/project-config-loader.test.ts +5 -33
  160. package/src/__tests__/public-exports.test.ts +31 -11
  161. package/src/__tests__/public-type-surface.test.ts +2 -13
  162. package/src/__tests__/public-value-surface.test.ts +1 -7
  163. package/src/__tests__/skip-semantics.test.ts +21 -37
  164. package/src/__tests__/trace-analyzer-extra.test.ts +14 -14
  165. package/src/__tests__/trace-analyzer.test.ts +21 -21
  166. package/src/__tests__/trace-collector.test.ts +22 -22
  167. package/src/__tests__/traces.test.ts +27 -28
  168. package/src/cli/commands/CONTEXT.md +12 -9
  169. package/src/cli/commands/__tests__/check-read-count.test.ts +4 -15
  170. package/src/cli/commands/__tests__/check-skip-output.test.ts +14 -14
  171. package/src/cli/commands/__tests__/check.test.ts +14 -31
  172. package/src/cli/commands/__tests__/constraints-report.test.ts +12 -80
  173. package/src/cli/commands/__tests__/constraints-retire.test.ts +42 -231
  174. package/src/cli/commands/__tests__/init-governance-io.test.ts +12 -58
  175. package/src/cli/commands/__tests__/init-ondisk.test.ts +12 -20
  176. package/src/cli/commands/__tests__/init.test.ts +0 -11
  177. package/src/cli/commands/__tests__/project-path-anchoring.test.ts +2 -2
  178. package/src/cli/commands/__tests__/registry.test.ts +39 -3
  179. package/src/cli/commands/__tests__/report-extra.test.ts +4 -4
  180. package/src/cli/commands/__tests__/report.test.ts +1 -1
  181. package/src/cli/commands/__tests__/scaffold.test.ts +4 -14
  182. package/src/cli/commands/__tests__/status-analysis-wiring.test.ts +3 -3
  183. package/src/cli/commands/__tests__/status-extra.test.ts +14 -14
  184. package/src/cli/commands/__tests__/status.test.ts +12 -12
  185. package/src/cli/commands/__tests__/sync-docs-agents.test.ts +1 -1
  186. package/src/cli/commands/__tests__/sync-docs-table-layout.test.ts +259 -0
  187. package/src/cli/commands/check.ts +43 -82
  188. package/src/cli/commands/constraints-report.ts +4 -59
  189. package/src/cli/commands/constraints-retire.ts +49 -154
  190. package/src/cli/commands/constraints.ts +11 -26
  191. package/src/cli/commands/definitions.ts +2 -2
  192. package/src/cli/commands/init.ts +8 -179
  193. package/src/cli/commands/report.ts +19 -23
  194. package/src/cli/commands/scaffold-templates.ts +1 -37
  195. package/src/cli/commands/scaffold.ts +0 -11
  196. package/src/cli/commands/status.ts +10 -10
  197. package/src/cli/commands/sync-docs/agents-syncer.ts +4 -25
  198. package/src/cli/commands/sync-docs/capabilities-syncer.ts +139 -9
  199. package/src/cli/commands/sync-docs/index.ts +41 -4
  200. package/src/core/CONTEXT.md +9 -9
  201. package/src/core/constraints/__tests__/capability-counts.test.ts +5 -5
  202. package/src/core/constraints/__tests__/collect-constraints.test.ts +13 -8
  203. package/src/core/constraints/__tests__/git-evidence.test.ts +4 -7
  204. package/src/core/constraints/__tests__/injection-writer.test.ts +8 -61
  205. package/src/core/constraints/__tests__/run-env.test.ts +5 -34
  206. package/src/core/constraints/__tests__/trace-injection.test.ts +1 -1
  207. package/src/core/constraints/capabilities-parser.ts +17 -5
  208. package/src/core/constraints/checker.ts +39 -88
  209. package/src/core/constraints/checkers/__tests__/check-outcome.test.ts +5 -8
  210. package/src/core/constraints/checkers/__tests__/governance-presence.test.ts +1 -53
  211. package/src/core/constraints/checkers/__tests__/iron-flags.test.ts +5 -25
  212. package/src/core/constraints/checkers/docs-freshness.ts +1 -1
  213. package/src/core/constraints/checkers/governance-presence.ts +4 -3
  214. package/src/core/constraints/checkers/index.ts +4 -10
  215. package/src/core/constraints/checkers/iron-flags.ts +3 -12
  216. package/src/core/constraints/checkers/no-test-simplification.ts +1 -1
  217. package/src/core/constraints/checkers/types.ts +1 -1
  218. package/src/core/constraints/definitions/guidelines.ts +8 -25
  219. package/src/core/constraints/definitions/iron-laws.ts +9 -82
  220. package/src/core/constraints/definitions.ts +14 -15
  221. package/src/core/constraints/index.ts +4 -19
  222. package/src/core/constraints/injection-writer.ts +16 -61
  223. package/src/core/constraints/run-env.ts +1 -33
  224. package/src/core/constraints/usage-report.ts +8 -15
  225. package/src/core/effective-constraints.ts +14 -45
  226. package/src/core/index.ts +3 -10
  227. package/src/core/project-config-loader.ts +20 -145
  228. package/src/core/validators/passes-gate.ts +6 -6
  229. package/src/failure/CONTEXT.md +1 -1
  230. package/src/hooks/CONTEXT.md +12 -22
  231. package/src/hooks/__tests__/bootstrap.test.ts +24 -75
  232. package/src/hooks/bootstrap.ts +9 -48
  233. package/src/hooks/index.ts +5 -20
  234. package/src/index.ts +9 -31
  235. package/src/monitoring/__tests__/trace-file-anchoring.test.ts +1 -1
  236. package/src/monitoring/__tests__/traces.test.ts +22 -22
  237. package/src/monitoring/trace-analyzer.ts +12 -13
  238. package/src/monitoring/traces.ts +8 -8
  239. package/src/presets/__tests__/standard.test.ts +12 -16
  240. package/src/presets/standard.ts +14 -23
  241. package/src/types/__tests__/types.test.ts +3 -3
  242. package/src/types/constraint.ts +26 -40
  243. package/src/types/passes-gate.ts +5 -5
  244. package/src/types/project-config.ts +8 -77
  245. package/src/types/trace.ts +8 -11
  246. package/dist/core/constraints/agent-prompt-renderer.d.ts +0 -32
  247. package/dist/core/constraints/agent-prompt-renderer.d.ts.map +0 -1
  248. package/dist/core/constraints/agent-prompt-renderer.js +0 -55
  249. package/dist/core/constraints/agent-prompt-renderer.js.map +0 -1
  250. package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts +0 -6
  251. package/dist/core/constraints/checkers/no-bypass-checkpoint.d.ts.map +0 -1
  252. package/dist/core/constraints/checkers/no-bypass-checkpoint.js +0 -40
  253. package/dist/core/constraints/checkers/no-bypass-checkpoint.js.map +0 -1
  254. package/dist/core/constraints/definitions/prompts.d.ts +0 -12
  255. package/dist/core/constraints/definitions/prompts.d.ts.map +0 -1
  256. package/dist/core/constraints/definitions/prompts.js +0 -400
  257. package/dist/core/constraints/definitions/prompts.js.map +0 -1
  258. package/dist/core/constraints/injection-drift.d.ts +0 -61
  259. package/dist/core/constraints/injection-drift.d.ts.map +0 -1
  260. package/dist/core/constraints/injection-drift.js +0 -131
  261. package/dist/core/constraints/injection-drift.js.map +0 -1
  262. package/dist/core/constraints/injection-renderer.d.ts +0 -23
  263. package/dist/core/constraints/injection-renderer.d.ts.map +0 -1
  264. package/dist/core/constraints/injection-renderer.js +0 -44
  265. package/dist/core/constraints/injection-renderer.js.map +0 -1
  266. package/dist/hooks/config.d.ts +0 -30
  267. package/dist/hooks/config.d.ts.map +0 -1
  268. package/dist/hooks/config.js +0 -34
  269. package/dist/hooks/config.js.map +0 -1
  270. package/dist/hooks/pipeline.d.ts +0 -54
  271. package/dist/hooks/pipeline.d.ts.map +0 -1
  272. package/dist/hooks/pipeline.js +0 -173
  273. package/dist/hooks/pipeline.js.map +0 -1
  274. package/dist/hooks/registry.d.ts +0 -70
  275. package/dist/hooks/registry.d.ts.map +0 -1
  276. package/dist/hooks/registry.js +0 -141
  277. package/dist/hooks/registry.js.map +0 -1
  278. package/dist/hooks/types.d.ts +0 -113
  279. package/dist/hooks/types.d.ts.map +0 -1
  280. package/dist/hooks/types.js +0 -9
  281. package/dist/hooks/types.js.map +0 -1
  282. package/src/__tests__/hooks-pipeline.test.ts +0 -201
  283. package/src/cli/commands/__tests__/check-drift.test.ts +0 -158
  284. package/src/cli/commands/__tests__/init-injection.test.ts +0 -466
  285. package/src/core/constraints/__tests__/agent-prompt-renderer.test.ts +0 -129
  286. package/src/core/constraints/__tests__/injection-drift.test.ts +0 -247
  287. package/src/core/constraints/agent-prompt-renderer.ts +0 -67
  288. package/src/core/constraints/checkers/__tests__/no-bypass-checkpoint.test.ts +0 -76
  289. package/src/core/constraints/checkers/no-bypass-checkpoint.ts +0 -40
  290. package/src/core/constraints/definitions/prompts.ts +0 -414
  291. package/src/core/constraints/injection-drift.ts +0 -142
  292. package/src/core/constraints/injection-renderer.ts +0 -44
  293. package/src/hooks/__tests__/config.test.ts +0 -19
  294. package/src/hooks/__tests__/pipeline.test.ts +0 -195
  295. package/src/hooks/__tests__/registry.test.ts +0 -115
  296. package/src/hooks/config.ts +0 -33
  297. package/src/hooks/pipeline.ts +0 -202
  298. package/src/hooks/registry.ts +0 -166
  299. package/src/hooks/types.ts +0 -120
@@ -54,9 +54,9 @@ describe('ConstraintChecker - 补充覆盖', () => {
54
54
 
55
55
  const result = checker.findApplicableConstraints(context);
56
56
 
57
- expect(result.ironLaws.length).toBeGreaterThan(0);
57
+ expect(result.errors.length).toBeGreaterThan(0);
58
58
  expect(
59
- result.ironLaws.some((c: any) => c.id === 'no_completion_without_verification')
59
+ result.errors.some(c => c.id === 'no_completion_without_verification')
60
60
  ).toBe(true);
61
61
  });
62
62
 
@@ -68,9 +68,9 @@ describe('ConstraintChecker - 补充覆盖', () => {
68
68
  const result = checker.findApplicableConstraints(context);
69
69
 
70
70
  // file_creation 可能没有任何约束匹配
71
- // 这个测试的目的是验证 filterByTrigger 逻辑
72
- expect(Array.isArray(result.ironLaws)).toBe(true);
73
- expect(Array.isArray(result.guidelines)).toBe(true);
71
+ // 这个测试的目的是验证按 trigger 过滤逻辑
72
+ expect(Array.isArray(result.errors)).toBe(true);
73
+ expect(Array.isArray(result.warnings)).toBe(true);
74
74
  });
75
75
  });
76
76
 
@@ -99,25 +99,25 @@ describe('ConstraintChecker - 补充覆盖', () => {
99
99
  await expect(checkBeforeExecution(context)).rejects.toThrow();
100
100
  });
101
101
 
102
- it('customConfig 应替换内置集(空配置不检查内置铁律)', async () => {
102
+ it('customConfig 应替换内置集(空配置不检查内置 error 级约束)', async () => {
103
103
  const context: ConstraintContext = {
104
104
  operation: 'code_implementation',
105
105
  hasTest: false,
106
106
  hasVerificationEvidence: false,
107
107
  };
108
108
 
109
- // 内置铁律下违规抛错
109
+ // 内置 error 级约束下违规抛错
110
110
  await expect(checkBeforeExecution(context)).rejects.toThrow();
111
111
 
112
112
  // 空 customConfig 替换内置集 → 不抛
113
113
  await expect(
114
- checkBeforeExecution(context, { ironLaws: {}, guidelines: {}, disabled: [], custom: [] })
114
+ checkBeforeExecution(context, { constraints: {}, disabled: [] })
115
115
  ).resolves.not.toThrow();
116
116
  });
117
117
  });
118
118
 
119
119
  describe('checkConstraints 完整流程', () => {
120
- it('应该返回完整的三层检查结果', async () => {
120
+ it('应该返回完整的检查结果', async () => {
121
121
  const context: ConstraintContext = {
122
122
  operation: 'commit',
123
123
  projectPath: tempDir,
@@ -127,8 +127,8 @@ describe('ConstraintChecker - 补充覆盖', () => {
127
127
 
128
128
  const result = await checkConstraints(context);
129
129
 
130
- expect(result.ironLaws).toBeDefined();
131
- expect(result.guidelines).toBeDefined();
130
+ expect(result.errors).toBeDefined();
131
+ expect(result.warnings).toBeDefined();
132
132
  expect(typeof result.passed).toBe('boolean');
133
133
  expect(typeof result.warningCount).toBe('number');
134
134
  });
@@ -137,80 +137,57 @@ describe('ConstraintChecker - 补充覆盖', () => {
137
137
  describe('自定义约束配置', () => {
138
138
  it('per-request customConfig 应该生效', () => {
139
139
  const constraints = checker.getConstraints({
140
- ironLaws: {},
141
- guidelines: {},
140
+ constraints: {},
142
141
  disabled: [],
143
- custom: [],
144
142
  });
145
143
 
146
- expect(constraints.ironLaws).toEqual({});
147
- expect(constraints.guidelines).toEqual({});
144
+ expect(constraints).toEqual({});
148
145
  });
149
146
 
150
- it('checkConstraint 带 customConfig 应命中自定义约束', async () => {
151
- const context: ConstraintContext = { operation: 'file_modification' };
147
+ it('checkConstraint 带 customConfig 应命中配置内约束', async () => {
148
+ const context: ConstraintContext = {
149
+ operation: 'code_implementation',
150
+ hasVerificationEvidence: true,
151
+ };
152
152
  const customConfig = {
153
- ironLaws: {
154
- test_only: {
155
- id: 'test_only',
156
- kind: 'prompt' as const,
157
- level: 'iron_law' as const,
153
+ constraints: {
154
+ no_completion_without_verification: {
155
+ id: 'no_completion_without_verification',
156
+ kind: 'check' as const,
157
+ severity: 'error' as const,
158
158
  rule: 'TEST',
159
159
  message: 'test',
160
- trigger: 'file_modification',
160
+ trigger: 'code_implementation',
161
161
  enforcement: 'test',
162
162
  },
163
163
  },
164
- guidelines: {},
165
164
  disabled: [] as string[],
166
- custom: [] as string[],
167
165
  };
168
166
 
169
- // 不带 customConfig:自定义约束不可见
167
+ // 不带 customConfig:未生效的 id 不可见
170
168
  const missing = await checkConstraint('test_only', context);
171
169
  expect(missing.satisfied).toBe(false);
172
170
  expect(missing.message).toContain('未知的约束');
173
171
 
174
- // 带 customConfig:命中(prompt kind 直接 pass)
175
- const hit = await checkConstraint('test_only', context, customConfig);
176
- expect(hit.id).toBe('test_only');
172
+ // 带 customConfig:命中配置内约束
173
+ const hit = await checkConstraint('no_completion_without_verification', context, customConfig);
174
+ expect(hit.id).toBe('no_completion_without_verification');
177
175
  expect(hit.satisfied).toBe(true);
178
176
  });
179
177
  });
180
178
 
181
- describe('getSeverity', () => {
182
- it('iron_law 应该返回 error', async () => {
183
- const context: ConstraintContext = {
184
- operation: 'code_implementation',
185
- hasTest: true,
186
- };
187
-
188
- const result = await checker.check(
189
- {
190
- id: 'test_severity_iron',
191
- kind: 'prompt',
192
- level: 'iron_law',
193
- rule: 'TEST',
194
- message: 'test',
195
- trigger: 'code_implementation',
196
- enforcement: 'test',
197
- },
198
- context
199
- );
200
-
201
- expect(result).toBeDefined();
202
- });
203
-
204
- it('guideline 应该返回 warning', async () => {
179
+ describe('severity 透传', () => {
180
+ it('check 结果带约束定义的 severity', async () => {
205
181
  const context: ConstraintContext = {
206
182
  operation: 'code_implementation',
183
+ hasVerificationEvidence: true,
207
184
  };
208
185
 
209
186
  const result = await checker.check(
210
187
  {
211
- id: 'test_severity_guideline',
212
- kind: 'prompt',
213
- level: 'guideline',
188
+ id: 'no_completion_without_verification',
189
+ kind: 'check',
190
+ severity: 'error',
214
191
  rule: 'TEST',
215
192
  message: 'test',
216
193
  trigger: 'code_implementation',
@@ -219,9 +196,8 @@ describe('ConstraintChecker - 补充覆盖', () => {
219
196
  context
220
197
  );
221
198
 
222
- expect(result).toBeDefined();
199
+ expect(result.severity).toBe('error');
223
200
  });
224
-
225
201
  });
226
202
 
227
203
  describe('checkConstraint 快捷函数', () => {
@@ -251,8 +227,8 @@ describe('ConstraintChecker - 补充覆盖', () => {
251
227
  });
252
228
  });
253
229
 
254
- describe('checkConstraints Iron Law 违规', () => {
255
- it('Iron Law 违规应该抛出 ConstraintViolationError', async () => {
230
+ describe('checkConstraints error 级违规', () => {
231
+ it('error 级违规应该抛出 ConstraintViolationError', async () => {
256
232
  const context: ConstraintContext = {
257
233
  operation: 'code_implementation',
258
234
  hasTest: false,
@@ -1,15 +1,13 @@
1
1
  /**
2
2
  * checker.ts 测试
3
3
  *
4
- * ADR-0001:只覆盖存活 check 约束的 checker 行为;
5
- * prompt 类约束的短路语义见 'Prompt constraints' 一节;
6
- * 已退役/被吸收约束的用例随之移除。
4
+ * ADR-0029:只覆盖存活 check 约束的 checker 行为;
5
+ * prompt 面已删除,其短路用例随之移除。
7
6
  */
8
7
 
9
8
  import { ConstraintChecker, checkConstraint } from '../core/constraints/checker';
10
- import { PROMPTS } from '../core/constraints/definitions';
11
9
  import type { ConstraintContext } from '../types/constraint';
12
- import { writeFileSync, rmSync, mkdtempSync } from 'fs';
10
+ import { rmSync, mkdtempSync } from 'fs';
13
11
  import { join } from 'path';
14
12
  import { tmpdir } from 'os';
15
13
 
@@ -31,42 +29,7 @@ describe('ConstraintChecker', () => {
31
29
  }
32
30
  });
33
31
 
34
- describe('Iron Laws', () => {
35
- it('should check no_bypass_checkpoint with skip patterns', async () => {
36
- // 创建包含 skip 的文件
37
- const skipFile = join(tempDir, 'skip-test.ts');
38
- writeFileSync(skipFile, 'test.skip("skipped test", () => {});');
39
-
40
- const context: ConstraintContext = {
41
- operation: 'code_implementation',
42
- changedFiles: [skipFile],
43
- };
44
-
45
- const result = await checker.check(
46
- { id: 'no_bypass_checkpoint', kind: 'check', level: 'guideline', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
47
- context
48
- );
49
-
50
- expect(result.satisfied).toBe(false);
51
- });
52
-
53
- it('should pass no_bypass_checkpoint without skip patterns', async () => {
54
- const normalFile = join(tempDir, 'normal-test.ts');
55
- writeFileSync(normalFile, 'test("normal test", () => { expect(true).toBe(true); });');
56
-
57
- const context: ConstraintContext = {
58
- operation: 'code_implementation',
59
- changedFiles: [normalFile],
60
- };
61
-
62
- const result = await checker.check(
63
- { id: 'no_bypass_checkpoint', kind: 'check', level: 'guideline', rule: 'NO BYPASS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
64
- context
65
- );
66
-
67
- expect(result.satisfied).toBe(true);
68
- });
69
-
32
+ describe('error 级约束', () => {
70
33
  it('should check no_completion_without_verification', async () => {
71
34
  const contextWithEvidence: ConstraintContext = {
72
35
  operation: 'code_implementation',
@@ -79,71 +42,21 @@ describe('ConstraintChecker', () => {
79
42
  };
80
43
 
81
44
  const resultWithEvidence = await checker.check(
82
- { id: 'no_completion_without_verification', kind: 'check', level: 'iron_law', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
45
+ { id: 'no_completion_without_verification', kind: 'check', severity: 'error', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
83
46
  contextWithEvidence
84
47
  );
85
48
 
86
49
  const resultWithoutEvidence = await checker.check(
87
- { id: 'no_completion_without_verification', kind: 'check', level: 'iron_law', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
50
+ { id: 'no_completion_without_verification', kind: 'check', severity: 'error', rule: 'NO COMPLETION', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
88
51
  contextWithoutEvidence
89
52
  );
90
53
 
91
54
  expect(resultWithEvidence.satisfied).toBe(true);
92
55
  expect(resultWithoutEvidence.satisfied).toBe(false);
93
56
  });
94
-
95
- it('should check incremental_progress', async () => {
96
- const contextWithSingleTask: ConstraintContext = {
97
- operation: 'code_implementation',
98
- hasSingleTask: true,
99
- };
100
-
101
- const contextWithMultipleTasks: ConstraintContext = {
102
- operation: 'code_implementation',
103
- hasSingleTask: false,
104
- };
105
-
106
- const resultWith = await checker.check(
107
- { id: 'incremental_progress', kind: 'check', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
108
- contextWithSingleTask
109
- );
110
-
111
- const resultWithout = await checker.check(
112
- { id: 'incremental_progress', kind: 'check', level: 'iron_law', rule: 'ONE TASK', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
113
- contextWithMultipleTasks
114
- );
115
-
116
- expect(resultWith.satisfied).toBe(true);
117
- expect(resultWithout.satisfied).toBe(false);
118
- });
119
-
120
- it('should check no_implementation_without_requirement', async () => {
121
- const contextWithRequirement: ConstraintContext = {
122
- operation: 'code_implementation',
123
- hasRequirement: true,
124
- };
125
-
126
- const contextWithoutRequirement: ConstraintContext = {
127
- operation: 'code_implementation',
128
- hasRequirement: false,
129
- };
130
-
131
- const resultWith = await checker.check(
132
- { id: 'no_implementation_without_requirement', kind: 'check', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
133
- contextWithRequirement
134
- );
135
-
136
- const resultWithout = await checker.check(
137
- { id: 'no_implementation_without_requirement', kind: 'check', level: 'iron_law', rule: 'REQ EXISTS', message: 'test', trigger: 'code_implementation', enforcement: 'test' },
138
- contextWithoutRequirement
139
- );
140
-
141
- expect(resultWith.satisfied).toBe(true);
142
- expect(resultWithout.satisfied).toBe(false);
143
- });
144
57
  });
145
58
 
146
- describe('Guidelines', () => {
59
+ describe('warning 级约束', () => {
147
60
  it('should check capability_sync without CAPABILITIES.md', async () => {
148
61
  // 注意:tempDir 在 harness 仓库内,如果有缓存的变更,会检查到代码变更
149
62
  // 所以需要创建一个无代码变更的场景或创建 CAPABILITIES.md
@@ -159,7 +72,7 @@ describe('ConstraintChecker', () => {
159
72
  fs.writeFileSync(capabilitiesPath, '# Capabilities\n');
160
73
 
161
74
  const result = await checker.check(
162
- { id: 'capability_sync', kind: 'check', level: 'guideline', rule: 'CAPABILITY SYNC', message: 'test', trigger: 'commit', enforcement: 'test' },
75
+ { id: 'capability_sync', kind: 'check', severity: 'warning', rule: 'CAPABILITY SYNC', message: 'test', trigger: 'commit', enforcement: 'test' },
163
76
  context
164
77
  );
165
78
 
@@ -171,24 +84,6 @@ describe('ConstraintChecker', () => {
171
84
  });
172
85
  });
173
86
 
174
- describe('Prompt constraints(ADR-0001:不执行 checker,check() 短路 satisfied)', () => {
175
- it('所有内置 prompt 约束 check() 均短路通过', async () => {
176
- const context: ConstraintContext = { operation: 'code_implementation' };
177
- for (const prompt of Object.values(PROMPTS)) {
178
- const result = await checker.check(prompt, context);
179
- expect(result.satisfied).toBe(true);
180
- }
181
- });
182
-
183
- it('prompt 短路不产生 requiredAction/message', async () => {
184
- const context: ConstraintContext = { operation: 'code_implementation' };
185
- const result = await checker.check(PROMPTS['no_fix_without_root_cause'], context);
186
- expect(result.satisfied).toBe(true);
187
- expect(result.message).toBeUndefined();
188
- expect(result.requiredAction).toBeUndefined();
189
- });
190
- });
191
-
192
87
  describe('Helper functions', () => {
193
88
  it('should check single constraint via checkConstraint', async () => {
194
89
  const context: ConstraintContext = {
@@ -205,8 +100,8 @@ describe('ConstraintChecker', () => {
205
100
  operation: 'code_implementation',
206
101
  };
207
102
 
208
- const result = await checkConstraint('no_fuzzy_completion_claim', context);
209
- expect(result.id).toBe('no_fuzzy_completion_claim');
103
+ const result = await checkConstraint('no_completion_without_verification', context);
104
+ expect(result.id).toBe('no_completion_without_verification');
210
105
  expect(result.satisfied).toBe(true);
211
106
  });
212
107
 
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * 生效约束集(getEffectiveConstraints / lintEffectiveConfig)测试
3
3
  *
4
- * 合并矩阵:preset 裁剪 / config.yml 禁用 / custom 追加 / scenes 过滤 / 未知 id 诊断
4
+ * 合并矩阵(ADR-0029):preset 裁剪 / config.yml 禁用 / 未知 id 诊断
5
+ * (custom 追加与 scenes 过滤已随文本注入层关停一并退役)
5
6
  */
6
7
 
7
8
  import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
@@ -11,25 +12,19 @@ import {
11
12
  lintEffectiveConfig,
12
13
  } from '../core/effective-constraints';
13
14
  import { createProjectFixture } from '../test-setup/project-fixture';
14
- import { IRON_LAWS, GUIDELINES, PROMPTS } from '../core/constraints/definitions';
15
+ import { CONSTRAINTS } from '../core/constraints/definitions';
15
16
 
16
- const BUILTIN_TOTAL =
17
- Object.keys(IRON_LAWS).length + Object.keys(GUIDELINES).length + Object.keys(PROMPTS).length;
18
- /** 带 appliesTo 标签的内置 prompt(scenes 过滤对象) */
19
- const SCENE_PROMPTS = Object.values(PROMPTS)
20
- .filter(c => c.appliesTo && c.appliesTo.length > 0)
21
- .map(c => c.id);
17
+ const BUILTIN_TOTAL = Object.keys(CONSTRAINTS).length;
22
18
 
23
19
  describe('getEffectiveConstraints / lintEffectiveConfig', () => {
24
20
  let tempDir: string;
25
21
  let counter = 0;
26
22
 
27
- const setupProject = (configYaml?: string, customYaml?: string): string =>
23
+ const setupProject = (configYaml?: string): string =>
28
24
  createProjectFixture({
29
25
  parentDir: tempDir,
30
26
  name: `p${counter++}`,
31
27
  config: configYaml,
32
- files: customYaml === undefined ? undefined : { '.harness/custom-constraints.yml': customYaml },
33
28
  });
34
29
 
35
30
  beforeEach(() => {
@@ -42,65 +37,28 @@ describe('getEffectiveConstraints / lintEffectiveConfig', () => {
42
37
  });
43
38
 
44
39
  describe('合并矩阵', () => {
45
- it('无配置项目:内置全集减去场景专属 prompt(scenes 缺省为空)', () => {
40
+ it('无配置项目:内置全集(全部 kind=check,带 severity)', () => {
46
41
  const dir = setupProject();
47
42
  const constraints = getEffectiveConstraints(dir);
48
- const ids = constraints.map(c => c.id);
49
-
50
- expect(constraints.length).toBe(BUILTIN_TOTAL - SCENE_PROMPTS.length);
51
- for (const id of SCENE_PROMPTS) {
52
- expect(ids).not.toContain(id);
53
- }
54
- // check + prompt 均带 kind
55
- expect(constraints.every(c => c.kind === 'check' || c.kind === 'prompt')).toBe(true);
56
- expect(constraints.filter(c => c.kind === 'check')).toHaveLength(
57
- Object.keys(IRON_LAWS).length + Object.keys(GUIDELINES).length
58
- );
59
- });
60
-
61
- it('scenes 命中:对应场景 prompt 进入生效集,其余场景 prompt 仍排除', () => {
62
- const dir = setupProject(`scenes:\n - agent-skill\n`);
63
- const ids = getEffectiveConstraints(dir).map(c => c.id);
64
43
 
65
- expect(ids).toContain('no_skill_without_test');
66
- expect(ids).not.toContain('no_model_for_deterministic');
44
+ expect(constraints.length).toBe(BUILTIN_TOTAL);
45
+ expect(constraints.every(c => c.kind === 'check')).toBe(true);
67
46
  });
68
47
 
69
- it('config.yml 禁用:check 与 prompt 条目均从生效集移除', () => {
48
+ it('config.yml 禁用:条目从生效集移除', () => {
70
49
  const dir = setupProject(`
71
50
  constraints:
72
- no_bypass_checkpoint:
51
+ capability_sync:
73
52
  enabled: false
74
- no_fuzzy_completion_claim:
53
+ docs_freshness:
75
54
  enabled: false
76
55
  `);
77
56
  const constraints = getEffectiveConstraints(dir);
78
57
  const ids = constraints.map(c => c.id);
79
58
 
80
- expect(ids).not.toContain('no_bypass_checkpoint');
81
- expect(ids).not.toContain('no_fuzzy_completion_claim');
82
- expect(constraints.length).toBe(BUILTIN_TOTAL - SCENE_PROMPTS.length - 2);
83
- });
84
-
85
- it('config.yml 禁用:custom 约束同样从生效集移除(retire 落 config.yml 的退役路径)', () => {
86
- const dir = setupProject(
87
- `
88
- constraints:
89
- my_project_rule:
90
- enabled: false
91
- `,
92
- `
93
- custom_constraints:
94
- my_project_rule:
95
- level: iron_law
96
- rule: MY RULE
97
- message: 项目自定义
98
- `
99
- );
100
- const constraints = getEffectiveConstraints(dir);
101
- const ids = constraints.map(c => c.id);
102
-
103
- expect(ids).not.toContain('my_project_rule');
59
+ expect(ids).not.toContain('capability_sync');
60
+ expect(ids).not.toContain('docs_freshness');
61
+ expect(constraints.length).toBe(BUILTIN_TOTAL - 2);
104
62
  });
105
63
 
106
64
  it('preset: relaxed 裁剪生效集', () => {
@@ -111,33 +69,13 @@ custom_constraints:
111
69
  expect(ids).toEqual(
112
70
  expect.arrayContaining([
113
71
  'no_completion_without_verification',
114
- 'incremental_progress',
115
- 'no_implementation_without_requirement',
116
- 'no_bypass_checkpoint',
117
72
  'no_hardcoded_credentials',
118
73
  ])
119
74
  );
120
- expect(constraints).toHaveLength(5);
75
+ expect(constraints).toHaveLength(2);
121
76
  expect(constraints.every(c => c.kind === 'check')).toBe(true);
122
77
  });
123
78
 
124
- it('custom-constraints.yml 追加自定义约束(kind=prompt)', () => {
125
- const dir = setupProject(undefined, `
126
- custom_constraints:
127
- my_project_rule:
128
- level: guideline
129
- rule: MY RULE
130
- message: 项目自定义
131
- trigger: code_implementation
132
- `);
133
- const constraints = getEffectiveConstraints(dir);
134
- const custom = constraints.find(c => c.id === 'my_project_rule');
135
-
136
- expect(custom).toBeDefined();
137
- expect(custom!.kind).toBe('prompt');
138
- expect(custom!.level).toBe('guideline');
139
- });
140
-
141
79
  it('禁用未知 id(已移除约束的残留配置):不报错,lint 可诊断', () => {
142
80
  const dir = setupProject(`
143
81
  constraints:
@@ -146,19 +84,16 @@ constraints:
146
84
  `);
147
85
  // 生效集不受影响、不抛错
148
86
  const constraints = getEffectiveConstraints(dir);
149
- expect(constraints.length).toBe(BUILTIN_TOTAL - SCENE_PROMPTS.length);
87
+ expect(constraints.length).toBe(BUILTIN_TOTAL);
150
88
 
151
89
  const lint = lintEffectiveConfig(dir);
152
90
  expect(lint.unknownIds).toContain('removed_legacy_constraint');
153
91
  });
154
92
 
155
- it('lintEffectiveConfig 报告 scenes 与被场景过滤的 prompt', () => {
156
- const dir = setupProject(`scenes:\n - llm-app\n`);
93
+ it('lintEffectiveConfig:干净配置 unknownIds 为空', () => {
94
+ const dir = setupProject();
157
95
  const lint = lintEffectiveConfig(dir);
158
96
 
159
- expect(lint.scenes).toEqual(['llm-app']);
160
- expect(lint.sceneExcluded).toContain('no_skill_without_test');
161
- expect(lint.sceneExcluded).not.toContain('no_model_for_deterministic');
162
97
  expect(lint.unknownIds).toEqual([]);
163
98
  });
164
99
  });