@dommaker/harness 1.1.1 → 1.2.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 (348) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +2 -4
  3. package/bin/harness.js +12 -37
  4. package/dist/cli/commands/check.d.ts +2 -2
  5. package/dist/cli/commands/check.d.ts.map +1 -1
  6. package/dist/cli/commands/check.js +7 -32
  7. package/dist/cli/commands/check.js.map +1 -1
  8. package/dist/cli/commands/definitions.d.ts +2 -0
  9. package/dist/cli/commands/definitions.d.ts.map +1 -1
  10. package/dist/cli/commands/definitions.js.map +1 -1
  11. package/dist/cli/commands/init.d.ts.map +1 -1
  12. package/dist/cli/commands/init.js +6 -37
  13. package/dist/cli/commands/init.js.map +1 -1
  14. package/dist/cli/commands/knowledge.d.ts.map +1 -1
  15. package/dist/cli/commands/knowledge.js +1 -12
  16. package/dist/cli/commands/knowledge.js.map +1 -1
  17. package/dist/cli/commands/report.d.ts.map +1 -1
  18. package/dist/cli/commands/report.js +0 -2
  19. package/dist/cli/commands/report.js.map +1 -1
  20. package/dist/cli/commands/status.js +2 -2
  21. package/dist/cli/commands/status.js.map +1 -1
  22. package/dist/context/index.d.ts +9 -6
  23. package/dist/context/index.d.ts.map +1 -1
  24. package/dist/context/index.js +18 -20
  25. package/dist/context/index.js.map +1 -1
  26. package/dist/core/constraints/capabilities-parser.d.ts +3 -2
  27. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  28. package/dist/core/constraints/capabilities-parser.js +25 -47
  29. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  30. package/dist/core/constraints/checker.d.ts +29 -32
  31. package/dist/core/constraints/checker.d.ts.map +1 -1
  32. package/dist/core/constraints/checker.js +34 -126
  33. package/dist/core/constraints/checker.js.map +1 -1
  34. package/dist/core/constraints/checkers/index.d.ts +2 -1
  35. package/dist/core/constraints/checkers/index.d.ts.map +1 -1
  36. package/dist/core/constraints/checkers/index.js +3 -0
  37. package/dist/core/constraints/checkers/index.js.map +1 -1
  38. package/dist/core/constraints/checkers/types.d.ts +25 -0
  39. package/dist/core/constraints/checkers/types.d.ts.map +1 -1
  40. package/dist/core/constraints/checkers/types.js +24 -0
  41. package/dist/core/constraints/checkers/types.js.map +1 -1
  42. package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -1
  43. package/dist/core/constraints/definitions/guidelines.js +0 -2
  44. package/dist/core/constraints/definitions/guidelines.js.map +1 -1
  45. package/dist/core/constraints/definitions/prompts.d.ts.map +1 -1
  46. package/dist/core/constraints/definitions/prompts.js +0 -5
  47. package/dist/core/constraints/definitions/prompts.js.map +1 -1
  48. package/dist/core/constraints/index.d.ts +1 -2
  49. package/dist/core/constraints/index.d.ts.map +1 -1
  50. package/dist/core/constraints/index.js +1 -7
  51. package/dist/core/constraints/index.js.map +1 -1
  52. package/dist/core/constraints/usage-report.d.ts +1 -2
  53. package/dist/core/constraints/usage-report.d.ts.map +1 -1
  54. package/dist/core/constraints/usage-report.js +2 -5
  55. package/dist/core/constraints/usage-report.js.map +1 -1
  56. package/dist/core/effective-constraints.d.ts +24 -4
  57. package/dist/core/effective-constraints.d.ts.map +1 -1
  58. package/dist/core/effective-constraints.js +28 -7
  59. package/dist/core/effective-constraints.js.map +1 -1
  60. package/dist/core/effective-set.d.ts +30 -0
  61. package/dist/core/effective-set.d.ts.map +1 -0
  62. package/dist/core/effective-set.js +35 -0
  63. package/dist/core/effective-set.js.map +1 -0
  64. package/dist/core/index.d.ts +13 -6
  65. package/dist/core/index.d.ts.map +1 -1
  66. package/dist/core/index.js +44 -21
  67. package/dist/core/index.js.map +1 -1
  68. package/dist/core/project-config-loader.d.ts +3 -6
  69. package/dist/core/project-config-loader.d.ts.map +1 -1
  70. package/dist/core/project-config-loader.js +47 -61
  71. package/dist/core/project-config-loader.js.map +1 -1
  72. package/dist/failure/constraint-handler.d.ts +1 -1
  73. package/dist/failure/constraint-handler.js +1 -1
  74. package/dist/gates/checker-gate.d.ts +1 -4
  75. package/dist/gates/checker-gate.d.ts.map +1 -1
  76. package/dist/gates/checker-gate.js +3 -11
  77. package/dist/gates/checker-gate.js.map +1 -1
  78. package/dist/gates/definitions.d.ts +9 -38
  79. package/dist/gates/definitions.d.ts.map +1 -1
  80. package/dist/gates/definitions.js +24 -13
  81. package/dist/gates/definitions.js.map +1 -1
  82. package/dist/gates/effective-gates.d.ts.map +1 -1
  83. package/dist/gates/effective-gates.js +14 -18
  84. package/dist/gates/effective-gates.js.map +1 -1
  85. package/dist/gates/index.d.ts +1 -1
  86. package/dist/gates/index.d.ts.map +1 -1
  87. package/dist/gates/index.js.map +1 -1
  88. package/dist/hooks/bootstrap.d.ts.map +1 -1
  89. package/dist/hooks/bootstrap.js +0 -3
  90. package/dist/hooks/bootstrap.js.map +1 -1
  91. package/dist/index.d.ts +43 -60
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +180 -143
  94. package/dist/index.js.map +1 -1
  95. package/dist/knowledge/query.d.ts +15 -0
  96. package/dist/knowledge/query.d.ts.map +1 -1
  97. package/dist/knowledge/query.js +23 -0
  98. package/dist/knowledge/query.js.map +1 -1
  99. package/dist/monitoring/analyzer-base.d.ts +0 -4
  100. package/dist/monitoring/analyzer-base.d.ts.map +1 -1
  101. package/dist/monitoring/analyzer-base.js +0 -21
  102. package/dist/monitoring/analyzer-base.js.map +1 -1
  103. package/dist/monitoring/index.d.ts +6 -12
  104. package/dist/monitoring/index.d.ts.map +1 -1
  105. package/dist/monitoring/index.js +13 -29
  106. package/dist/monitoring/index.js.map +1 -1
  107. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  108. package/dist/monitoring/trace-analyzer.js +2 -68
  109. package/dist/monitoring/trace-analyzer.js.map +1 -1
  110. package/dist/monitoring/traces.d.ts +0 -4
  111. package/dist/monitoring/traces.d.ts.map +1 -1
  112. package/dist/monitoring/traces.js +0 -14
  113. package/dist/monitoring/traces.js.map +1 -1
  114. package/dist/presets/index.d.ts +2 -2
  115. package/dist/presets/index.d.ts.map +1 -1
  116. package/dist/presets/index.js +3 -4
  117. package/dist/presets/index.js.map +1 -1
  118. package/dist/presets/standard.d.ts +10 -22
  119. package/dist/presets/standard.d.ts.map +1 -1
  120. package/dist/presets/standard.js +15 -75
  121. package/dist/presets/standard.js.map +1 -1
  122. package/dist/types/constraint.d.ts +1 -29
  123. package/dist/types/constraint.d.ts.map +1 -1
  124. package/dist/types/constraint.js +1 -1
  125. package/dist/types/constraint.js.map +1 -1
  126. package/dist/types/index.d.ts +0 -3
  127. package/dist/types/index.d.ts.map +1 -1
  128. package/dist/types/index.js +0 -4
  129. package/dist/types/index.js.map +1 -1
  130. package/dist/types/project-config.d.ts +4 -8
  131. package/dist/types/project-config.d.ts.map +1 -1
  132. package/dist/types/trace.d.ts +5 -18
  133. package/dist/types/trace.d.ts.map +1 -1
  134. package/package.json +2 -2
  135. package/src/CONTEXT.md +4 -5
  136. package/src/__tests__/checker-extra.test.ts +33 -139
  137. package/src/__tests__/checker.test.ts +0 -376
  138. package/src/__tests__/project-config-loader-extra.test.ts +42 -29
  139. package/src/__tests__/public-exports.test.ts +138 -0
  140. package/src/__tests__/trace-analyzer-extra.test.ts +6 -86
  141. package/src/__tests__/trace-analyzer.test.ts +4 -5
  142. package/src/__tests__/trace-collector.test.ts +0 -11
  143. package/src/__tests__/traces.test.ts +3 -22
  144. package/src/cli/commands/CONTEXT.md +2 -2
  145. package/src/cli/commands/__tests__/check-skip-output.test.ts +10 -7
  146. package/src/cli/commands/__tests__/check.test.ts +29 -69
  147. package/src/cli/commands/__tests__/constraints-report.test.ts +1 -1
  148. package/src/cli/commands/__tests__/knowledge.test.ts +90 -1
  149. package/src/cli/commands/__tests__/registry.test.ts +8 -6
  150. package/src/cli/commands/__tests__/status-extra.test.ts +6 -6
  151. package/src/cli/commands/__tests__/status.test.ts +6 -6
  152. package/src/cli/commands/check.ts +8 -34
  153. package/src/cli/commands/definitions.ts +2 -0
  154. package/src/cli/commands/init.ts +6 -37
  155. package/src/cli/commands/knowledge.ts +1 -16
  156. package/src/cli/commands/report.ts +0 -2
  157. package/src/cli/commands/status.ts +2 -2
  158. package/src/context/index.ts +29 -6
  159. package/src/core/CONTEXT.md +4 -3
  160. package/src/core/__tests__/effective-set.test.ts +80 -0
  161. package/src/core/constraints/capabilities-parser.ts +43 -49
  162. package/src/core/constraints/checker.ts +51 -145
  163. package/src/core/constraints/checkers/index.ts +2 -1
  164. package/src/core/constraints/checkers/types.ts +42 -0
  165. package/src/core/constraints/definitions/guidelines.ts +0 -2
  166. package/src/core/constraints/definitions/prompts.ts +0 -5
  167. package/src/core/constraints/index.ts +2 -17
  168. package/src/core/constraints/usage-report.ts +5 -8
  169. package/src/core/effective-constraints.ts +35 -7
  170. package/src/core/effective-set.ts +56 -0
  171. package/src/core/index.ts +80 -6
  172. package/src/core/project-config-loader.ts +53 -68
  173. package/src/failure/CONTEXT.md +1 -1
  174. package/src/failure/constraint-handler.ts +1 -1
  175. package/src/gates/CONTEXT.md +3 -3
  176. package/src/gates/checker-gate.ts +4 -12
  177. package/src/gates/definitions.ts +27 -50
  178. package/src/gates/effective-gates.ts +14 -21
  179. package/src/gates/index.ts +1 -1
  180. package/src/hooks/bootstrap.ts +0 -3
  181. package/src/index.ts +384 -148
  182. package/src/knowledge/CONTEXT.md +2 -2
  183. package/src/knowledge/__tests__/query.test.ts +64 -0
  184. package/src/knowledge/query.ts +28 -0
  185. package/src/monitoring/CONTEXT.md +7 -13
  186. package/src/monitoring/__tests__/traces.test.ts +0 -10
  187. package/src/monitoring/analyzer-base.ts +0 -22
  188. package/src/monitoring/index.ts +6 -12
  189. package/src/monitoring/trace-analyzer.ts +2 -73
  190. package/src/monitoring/traces.ts +0 -20
  191. package/src/presets/__tests__/standard.test.ts +48 -69
  192. package/src/presets/index.ts +3 -5
  193. package/src/presets/standard.ts +14 -79
  194. package/src/spec/CONTEXT.md +5 -13
  195. package/src/types/constraint.ts +1 -51
  196. package/src/types/index.ts +0 -12
  197. package/src/types/project-config.ts +4 -10
  198. package/src/types/trace.ts +5 -30
  199. package/dist/core/constraints/interceptor.d.ts +0 -39
  200. package/dist/core/constraints/interceptor.d.ts.map +0 -1
  201. package/dist/core/constraints/interceptor.js +0 -166
  202. package/dist/core/constraints/interceptor.js.map +0 -1
  203. package/dist/dashboard/data.d.ts +0 -31
  204. package/dist/dashboard/data.d.ts.map +0 -1
  205. package/dist/dashboard/data.js +0 -81
  206. package/dist/dashboard/data.js.map +0 -1
  207. package/dist/dashboard/index.d.ts +0 -4
  208. package/dist/dashboard/index.d.ts.map +0 -1
  209. package/dist/dashboard/index.js +0 -20
  210. package/dist/dashboard/index.js.map +0 -1
  211. package/dist/dashboard/stats.d.ts +0 -20
  212. package/dist/dashboard/stats.d.ts.map +0 -1
  213. package/dist/dashboard/stats.js +0 -115
  214. package/dist/dashboard/stats.js.map +0 -1
  215. package/dist/dashboard/types.d.ts +0 -110
  216. package/dist/dashboard/types.d.ts.map +0 -1
  217. package/dist/dashboard/types.js +0 -8
  218. package/dist/dashboard/types.js.map +0 -1
  219. package/dist/monitoring/constraint-doctor.d.ts +0 -76
  220. package/dist/monitoring/constraint-doctor.d.ts.map +0 -1
  221. package/dist/monitoring/constraint-doctor.js +0 -189
  222. package/dist/monitoring/constraint-doctor.js.map +0 -1
  223. package/dist/monitoring/diagnosis-rules.d.ts +0 -18
  224. package/dist/monitoring/diagnosis-rules.d.ts.map +0 -1
  225. package/dist/monitoring/diagnosis-rules.js +0 -119
  226. package/dist/monitoring/diagnosis-rules.js.map +0 -1
  227. package/dist/monitoring/knowledge-doctor.d.ts +0 -78
  228. package/dist/monitoring/knowledge-doctor.d.ts.map +0 -1
  229. package/dist/monitoring/knowledge-doctor.js +0 -266
  230. package/dist/monitoring/knowledge-doctor.js.map +0 -1
  231. package/dist/monitoring/knowledge-evolver.d.ts +0 -72
  232. package/dist/monitoring/knowledge-evolver.d.ts.map +0 -1
  233. package/dist/monitoring/knowledge-evolver.js +0 -205
  234. package/dist/monitoring/knowledge-evolver.js.map +0 -1
  235. package/dist/monitoring/performance-analyzer.d.ts +0 -92
  236. package/dist/monitoring/performance-analyzer.d.ts.map +0 -1
  237. package/dist/monitoring/performance-analyzer.js +0 -343
  238. package/dist/monitoring/performance-analyzer.js.map +0 -1
  239. package/dist/monitoring/performance-collector.d.ts +0 -103
  240. package/dist/monitoring/performance-collector.d.ts.map +0 -1
  241. package/dist/monitoring/performance-collector.js +0 -298
  242. package/dist/monitoring/performance-collector.js.map +0 -1
  243. package/dist/safety/index.d.ts +0 -6
  244. package/dist/safety/index.d.ts.map +0 -1
  245. package/dist/safety/index.js +0 -22
  246. package/dist/safety/index.js.map +0 -1
  247. package/dist/safety/input-guardrail.d.ts +0 -36
  248. package/dist/safety/input-guardrail.d.ts.map +0 -1
  249. package/dist/safety/input-guardrail.js +0 -118
  250. package/dist/safety/input-guardrail.js.map +0 -1
  251. package/dist/safety/output-guardrail.d.ts +0 -39
  252. package/dist/safety/output-guardrail.d.ts.map +0 -1
  253. package/dist/safety/output-guardrail.js +0 -147
  254. package/dist/safety/output-guardrail.js.map +0 -1
  255. package/dist/safety/sandbox.d.ts +0 -45
  256. package/dist/safety/sandbox.d.ts.map +0 -1
  257. package/dist/safety/sandbox.js +0 -134
  258. package/dist/safety/sandbox.js.map +0 -1
  259. package/dist/safety/tool-guardrail.d.ts +0 -51
  260. package/dist/safety/tool-guardrail.d.ts.map +0 -1
  261. package/dist/safety/tool-guardrail.js +0 -147
  262. package/dist/safety/tool-guardrail.js.map +0 -1
  263. package/dist/safety/types.d.ts +0 -104
  264. package/dist/safety/types.d.ts.map +0 -1
  265. package/dist/safety/types.js +0 -6
  266. package/dist/safety/types.js.map +0 -1
  267. package/dist/spec/annotation-checker.d.ts +0 -47
  268. package/dist/spec/annotation-checker.d.ts.map +0 -1
  269. package/dist/spec/annotation-checker.js +0 -279
  270. package/dist/spec/annotation-checker.js.map +0 -1
  271. package/dist/types/enforcement.d.ts +0 -42
  272. package/dist/types/enforcement.d.ts.map +0 -1
  273. package/dist/types/enforcement.js +0 -6
  274. package/dist/types/enforcement.js.map +0 -1
  275. package/dist/types/monitoring-types.d.ts +0 -53
  276. package/dist/types/monitoring-types.d.ts.map +0 -1
  277. package/dist/types/monitoring-types.js +0 -10
  278. package/dist/types/monitoring-types.js.map +0 -1
  279. package/dist/types/performance.d.ts +0 -204
  280. package/dist/types/performance.d.ts.map +0 -1
  281. package/dist/types/performance.js +0 -12
  282. package/dist/types/performance.js.map +0 -1
  283. package/dist/verification/index.d.ts +0 -4
  284. package/dist/verification/index.d.ts.map +0 -1
  285. package/dist/verification/index.js +0 -20
  286. package/dist/verification/index.js.map +0 -1
  287. package/dist/verification/loop.d.ts +0 -30
  288. package/dist/verification/loop.d.ts.map +0 -1
  289. package/dist/verification/loop.js +0 -114
  290. package/dist/verification/loop.js.map +0 -1
  291. package/dist/verification/rules-based.d.ts +0 -40
  292. package/dist/verification/rules-based.d.ts.map +0 -1
  293. package/dist/verification/rules-based.js +0 -130
  294. package/dist/verification/rules-based.js.map +0 -1
  295. package/dist/verification/types.d.ts +0 -69
  296. package/dist/verification/types.d.ts.map +0 -1
  297. package/dist/verification/types.js +0 -6
  298. package/dist/verification/types.js.map +0 -1
  299. package/src/__tests__/annotation-checker.test.ts +0 -183
  300. package/src/__tests__/constraint-doctor.test.ts +0 -271
  301. package/src/__tests__/doctor-extra.test.ts +0 -155
  302. package/src/__tests__/extend-exceptions.test.ts +0 -149
  303. package/src/__tests__/interceptor.test.ts +0 -89
  304. package/src/__tests__/performance-analyzer.test.ts +0 -499
  305. package/src/__tests__/performance-collector.test.ts +0 -276
  306. package/src/__tests__/presets.test.ts +0 -65
  307. package/src/core/constraints/__tests__/interceptor.test.ts +0 -267
  308. package/src/core/constraints/interceptor.ts +0 -217
  309. package/src/dashboard/CONTEXT.md +0 -21
  310. package/src/dashboard/__tests__/data.test.ts +0 -111
  311. package/src/dashboard/__tests__/stats.test.ts +0 -159
  312. package/src/dashboard/data.ts +0 -103
  313. package/src/dashboard/index.ts +0 -3
  314. package/src/dashboard/stats.ts +0 -127
  315. package/src/dashboard/types.ts +0 -130
  316. package/src/monitoring/__tests__/knowledge-doctor.test.ts +0 -278
  317. package/src/monitoring/__tests__/knowledge-evolver.test.ts +0 -368
  318. package/src/monitoring/__tests__/performance-analyzer.test.ts +0 -137
  319. package/src/monitoring/__tests__/performance-collector.test.ts +0 -331
  320. package/src/monitoring/constraint-doctor.ts +0 -228
  321. package/src/monitoring/diagnosis-rules.ts +0 -132
  322. package/src/monitoring/knowledge-doctor.ts +0 -322
  323. package/src/monitoring/knowledge-evolver.ts +0 -289
  324. package/src/monitoring/performance-analyzer.ts +0 -400
  325. package/src/monitoring/performance-collector.ts +0 -326
  326. package/src/safety/CONTEXT.md +0 -23
  327. package/src/safety/__tests__/input-guardrail.test.ts +0 -105
  328. package/src/safety/__tests__/output-guardrail.test.ts +0 -108
  329. package/src/safety/__tests__/sandbox.test.ts +0 -158
  330. package/src/safety/__tests__/tool-guardrail.test.ts +0 -127
  331. package/src/safety/index.ts +0 -5
  332. package/src/safety/input-guardrail.ts +0 -133
  333. package/src/safety/output-guardrail.ts +0 -170
  334. package/src/safety/sandbox.ts +0 -148
  335. package/src/safety/tool-guardrail.ts +0 -176
  336. package/src/safety/types.ts +0 -124
  337. package/src/spec/__tests__/annotation-checker.test.ts +0 -294
  338. package/src/spec/annotation-checker.ts +0 -320
  339. package/src/types/enforcement.ts +0 -48
  340. package/src/types/monitoring-types.ts +0 -68
  341. package/src/types/performance.ts +0 -295
  342. package/src/verification/CONTEXT.md +0 -23
  343. package/src/verification/__tests__/loop.test.ts +0 -303
  344. package/src/verification/__tests__/rules-based.test.ts +0 -240
  345. package/src/verification/index.ts +0 -3
  346. package/src/verification/loop.ts +0 -137
  347. package/src/verification/rules-based.ts +0 -152
  348. package/src/verification/types.ts +0 -81
@@ -65,22 +65,21 @@ describe('TraceAnalyzer - 补充覆盖', () => {
65
65
  describe('compareWithPrevious', () => {
66
66
  it('应该计算环比变化', () => {
67
67
  const current: any[] = [
68
- { constraintId: 'test', passRate: 0.8, failRate: 0.2, bypassRate: 0.1, level: 'iron_law' },
68
+ { constraintId: 'test', passRate: 0.8, failRate: 0.2, level: 'iron_law' },
69
69
  ];
70
70
  const previous: any[] = [
71
- { constraintId: 'test', passRate: 0.6, failRate: 0.4, bypassRate: 0.2, level: 'iron_law' },
71
+ { constraintId: 'test', passRate: 0.6, failRate: 0.4, level: 'iron_law' },
72
72
  ];
73
73
 
74
74
  const result = analyzer.compareWithPrevious(current, previous);
75
-
75
+
76
76
  expect(result[0]?.changeFromLastPeriod?.passRateDelta).toBeCloseTo(0.2);
77
77
  expect(result[0]?.changeFromLastPeriod?.failRateDelta).toBeCloseTo(-0.2);
78
- expect(result[0]?.changeFromLastPeriod?.bypassRateDelta).toBeCloseTo(-0.1);
79
78
  });
80
79
 
81
80
  it('无历史数据应该不设置变化', () => {
82
81
  const current: any[] = [
83
- { constraintId: 'new_test', passRate: 0.8, failRate: 0.2, bypassRate: 0.1, level: 'iron_law' },
82
+ { constraintId: 'new_test', passRate: 0.8, failRate: 0.2, level: 'iron_law' },
84
83
  ];
85
84
  const previous: any[] = [];
86
85
 
@@ -93,7 +92,7 @@ describe('TraceAnalyzer - 补充覆盖', () => {
93
92
  describe('saveSummary/loadSummary', () => {
94
93
  it('应该保存和加载汇总', () => {
95
94
  const summaries: any[] = [
96
- { constraintId: 'test', passRate: 0.8, failRate: 0.2, bypassRate: 0.1, level: 'iron_law', totalChecks: 10 },
95
+ { constraintId: 'test', passRate: 0.8, failRate: 0.2, level: 'iron_law', totalChecks: 10 },
97
96
  ];
98
97
 
99
98
  analyzer.saveSummary(summaries);
@@ -157,7 +156,6 @@ describe('TraceAnalyzer - 补充覆盖', () => {
157
156
  level: 'iron_law',
158
157
  passRate: 0.8,
159
158
  failRate: 0.2,
160
- bypassRate: 0.1,
161
159
  totalChecks: 100,
162
160
  recentTrend: 'stable',
163
161
  },
@@ -190,46 +188,6 @@ describe('TraceAnalyzer - 补充覆盖', () => {
190
188
  });
191
189
  });
192
190
 
193
- describe('findMostCommon', () => {
194
- it('应该找出最常见元素', () => {
195
- // 通过 bypassReasons 统计来触发
196
- const traces: ExecutionTrace[] = [
197
- { constraintId: 'common_test', level: 'iron_law', timestamp: 1000, result: 'pass' },
198
- { constraintId: 'common_test', level: 'iron_law', timestamp: 2000, result: 'pass', bypassReason: 'reason_a' },
199
- { constraintId: 'common_test', level: 'iron_law', timestamp: 3000, result: 'pass', bypassReason: 'reason_a' },
200
- { constraintId: 'common_test', level: 'iron_law', timestamp: 4000, result: 'pass', bypassReason: 'reason_b' },
201
- ];
202
-
203
- const summaries = analyzer.summarize(traces);
204
-
205
- // 验证汇总结果存在
206
- expect(summaries.length).toBeGreaterThan(0);
207
- });
208
-
209
- it('应该通过 exceptionApplied 触发 findMostCommon', () => {
210
- const traces: ExecutionTrace[] = [
211
- { constraintId: 'exc_test', level: 'guideline', timestamp: 1000, result: 'pass', exceptionApplied: 'simple_typo' },
212
- { constraintId: 'exc_test', level: 'guideline', timestamp: 2000, result: 'pass', exceptionApplied: 'simple_typo' },
213
- { constraintId: 'exc_test', level: 'guideline', timestamp: 3000, result: 'pass', exceptionApplied: 'config_error' },
214
- ];
215
-
216
- const summaries = analyzer.summarize(traces);
217
- const summary = summaries.find(s => s.constraintId === 'exc_test');
218
-
219
- expect(summary?.exceptionCount).toBe(3);
220
- expect(summary?.mostCommonException).toBe('simple_typo');
221
- });
222
-
223
- it('无 exception 时 mostCommonException 应该是 undefined', () => {
224
- const traces: ExecutionTrace[] = [
225
- { constraintId: 'no_exc', level: 'iron_law', timestamp: 1000, result: 'pass' },
226
- ];
227
-
228
- const summaries = analyzer.summarize(traces);
229
- expect(summaries[0]?.mostCommonException).toBeUndefined();
230
- });
231
- });
232
-
233
191
  describe('detectAnomalies - 更多异常类型', () => {
234
192
  it('应该检测 rising_fail_rate', () => {
235
193
  // 前半段全 fail,后半段全 pass → rising 趋势
@@ -253,44 +211,6 @@ describe('TraceAnalyzer - 补充覆盖', () => {
253
211
  const risingFail = anomalies.find(a => a.type === 'rising_fail_rate');
254
212
  expect(risingFail).toBeDefined();
255
213
  });
256
-
257
- it('应该检测 rising_bypass_rate', () => {
258
- // 前半段全 fail,后半段混合 pass+bypass → rising 趋势
259
- // bypassRate 需要 > 0.1,且 trend === 'rising'
260
- const traces: ExecutionTrace[] = [];
261
- for (let i = 0; i < 6; i++) {
262
- traces.push({ constraintId: 'rising_bypass', level: 'guideline', timestamp: 1000 + i * 100, result: 'fail' });
263
- }
264
- for (let i = 6; i < 14; i++) {
265
- // 后半段有 pass 也有 bypass,使 passRate 上升(rising),同时 bypassRate > 0.1
266
- traces.push({ constraintId: 'rising_bypass', level: 'guideline', timestamp: 1000 + i * 100, result: i % 2 === 0 ? 'pass' : 'bypassed' });
267
- }
268
-
269
- const summaries = analyzer.summarize(traces);
270
- const anomalies = analyzer.detectAnomalies(summaries);
271
-
272
- const risingBypass = anomalies.find(a => a.type === 'rising_bypass_rate');
273
- expect(risingBypass).toBeDefined();
274
- });
275
-
276
- it('应该检测 exception_overuse', () => {
277
- const traces: ExecutionTrace[] = [];
278
- for (let i = 0; i < 10; i++) {
279
- traces.push({
280
- constraintId: 'exc_overuse',
281
- level: 'guideline',
282
- timestamp: 1000 + i * 100,
283
- result: 'pass',
284
- exceptionApplied: i < 8 ? 'simple_typo' : undefined,
285
- });
286
- }
287
-
288
- const summaries = analyzer.summarize(traces);
289
- const anomalies = analyzer.detectAnomalies(summaries);
290
-
291
- const excOveruse = anomalies.find(a => a.type === 'exception_overuse');
292
- expect(excOveruse).toBeDefined();
293
- });
294
214
  });
295
215
 
296
216
  describe('createAnalyzer 工厂函数', () => {
@@ -300,7 +220,7 @@ describe('TraceAnalyzer - 补充覆盖', () => {
300
220
  });
301
221
 
302
222
  it('应该支持自定义配置', () => {
303
- const a = createAnalyzer({ thresholds: { bypassRate: 0.05 } });
223
+ const a = createAnalyzer({ thresholds: { failRate: 0.05 } });
304
224
  expect(a).toBeDefined();
305
225
  });
306
226
  });
@@ -75,11 +75,11 @@ describe('TraceAnalyzer', () => {
75
75
  });
76
76
 
77
77
  describe('detectAnomalies', () => {
78
- it('应该检测高绕过率异常', () => {
78
+ it('应该检测失败率异常', () => {
79
79
  const traces: ExecutionTrace[] = [
80
- { constraintId: 'test', level: 'guideline', timestamp: 1000, result: 'bypassed' },
81
- { constraintId: 'test', level: 'guideline', timestamp: 2000, result: 'bypassed' },
82
- { constraintId: 'test', level: 'guideline', timestamp: 3000, result: 'bypassed' },
80
+ { constraintId: 'test', level: 'guideline', timestamp: 1000, result: 'fail' },
81
+ { constraintId: 'test', level: 'guideline', timestamp: 2000, result: 'fail' },
82
+ { constraintId: 'test', level: 'guideline', timestamp: 3000, result: 'fail' },
83
83
  { constraintId: 'test', level: 'guideline', timestamp: 4000, result: 'pass' },
84
84
  ];
85
85
 
@@ -120,7 +120,6 @@ describe('TraceAnalyzer', () => {
120
120
  it('应该支持自定义阈值', () => {
121
121
  const customAnalyzer = new TraceAnalyzer(collector, {
122
122
  thresholds: {
123
- bypassRate: 0.1,
124
123
  failRate: 0.2,
125
124
  },
126
125
  });
@@ -104,17 +104,6 @@ describe('TraceCollector', () => {
104
104
  });
105
105
  });
106
106
 
107
- describe('recordBypass', () => {
108
- it('应该记录绕过 trace', () => {
109
- collector.recordBypass('no_bypass_checkpoint', 'iron_law', 'Emergency fix');
110
-
111
- const traces = collector.read();
112
- expect(traces.length).toBe(1);
113
- expect(traces[0].result).toBe('bypassed');
114
- expect(traces[0].bypassReason).toBe('Emergency fix');
115
- });
116
- });
117
-
118
107
  describe('read', () => {
119
108
  it('应该返回所有 traces', () => {
120
109
  collector.record({
@@ -57,7 +57,7 @@ describe('TraceCollector', () => {
57
57
  test('should filter traces by constraint ID', () => {
58
58
  collector.recordPass('constraint_a', 'iron_law');
59
59
  collector.recordFail('constraint_b', 'guideline');
60
- collector.recordBypass('constraint_a', 'iron_law', 'user reason');
60
+ collector.recordFail('constraint_a', 'iron_law');
61
61
 
62
62
  const traces = collector.read({ constraintId: 'constraint_a' });
63
63
  expect(traces.length).toBe(2);
@@ -226,7 +226,7 @@ describe('TraceAnalyzer', () => {
226
226
  constraintId: 'constraint_b',
227
227
  level: 'iron_law',
228
228
  timestamp: Date.now() - i * 60 * 1000,
229
- result: i < 3 ? 'pass' : 'bypassed',
229
+ result: i < 3 ? 'pass' : 'fail',
230
230
  });
231
231
  }
232
232
 
@@ -243,26 +243,7 @@ describe('TraceAnalyzer', () => {
243
243
 
244
244
  const summaryB = summaries.find(s => s.constraintId === 'constraint_b');
245
245
  expect(summaryB).toBeDefined();
246
- expect(summaryB!.bypassRate).toBeCloseTo(0.4, 1);
247
- });
248
-
249
- test('should detect high bypass rate anomaly', () => {
250
- // 记录高绕过率的 traces
251
- for (let i = 0; i < 10; i++) {
252
- collector.record({
253
- constraintId: 'problematic_constraint',
254
- level: 'guideline',
255
- timestamp: Date.now(),
256
- result: i < 3 ? 'pass' : 'bypassed', // 70% 绕过率
257
- });
258
- }
259
-
260
- const traces = collector.read();
261
- const summaries = analyzer.summarize(traces);
262
- const anomalies = analyzer.detectAnomalies(summaries);
263
-
264
- expect(anomalies.length).toBeGreaterThan(0);
265
- expect(anomalies.some(a => a.type === 'high_bypass_rate')).toBe(true);
246
+ expect(summaryB!.failRate).toBeCloseTo(0.4, 1);
266
247
  });
267
248
 
268
249
  test('should detect rising fail rate anomaly', () => {
@@ -10,7 +10,7 @@ H5(#44)起:
10
10
  ## 核心导出
11
11
  - `COMMAND_DEFINITIONS`(definitions.ts)— 全部非门禁命令定义(纯数据模块,禁止 import 命令实现)
12
12
  - 各命令文件:check / validate / passes-gate / init / report / status / spec / sync-docs / knowledge / sdd / failure / posteval-plan / release / analyze-sessions / update-user-model / constraints / doc-freshness-check / spec-baseline-check
13
- - 6 门禁命令实现在 `acceptance` / `command` / `contract` / `performance` / `review` / `security`(其 CLI 元数据在 `src/gates/definitions.ts`)
13
+ - 6 门禁命令实现在 `acceptance` / `command` / `contract` / `performance` / `review` / `security`(其 CLI 元数据在 `src/gates/definitions.ts`,形状同为 `CommandDefinition`,ADR-0007)
14
14
 
15
15
  `constraints` 下挂治理子命令:`constraints report`(使用统计 + 退役候选诊断 + 配置健康 + 注入漂移,`--export` 脱敏)、`constraints retire`(交互选择 + 人确认退役;带 id 直达需显式 `--yes`(#24 人确认闸门),无 `--yes` 报错 + 非零退出码且不落盘;内置落 config.yml retired 元数据,custom 落 custom-constraints.yml 条目 retired 段(#82 D6 一处真相)+ KnowledgeStore 沉淀 + CLAUDE.md 注入段同步)。
16
16
 
@@ -31,4 +31,4 @@ H5(#44)起:
31
31
  ## 注意事项
32
32
  - 新增命令需同步更新 CLAUDE.md / CAPABILITIES.md / src/CONTEXT.md
33
33
  - knowledge 命令包含 13 个子操作(list/search/import/decay/stats/upsert/sync-status/sync-rag/audit/snapshot/migrate/index/health)
34
- - 特殊路由(选项条件、子命令兜底、退出码处理)表达在定义表的 optionRoutes / subcommands / afterRun 字段,bin 是纯通用引擎、不含单命令知识
34
+ - 特殊路由(选项条件、子命令兜底、退出码处理、裸跑语义)表达在定义表的 optionRoutes / subcommands / subcommandStrict / bareRunsAction / afterRun 字段,bin 是纯通用引擎、不含单命令知识
@@ -34,13 +34,16 @@ jest.mock('../../../core/constraints/checker', () => ({
34
34
  },
35
35
  }));
36
36
 
37
- // Mock ProjectConfigLoader
38
- jest.mock('../../../core/project-config-loader', () => ({
39
- ProjectConfigLoader: jest.fn().mockImplementation(() => ({
40
- load: jest.fn(),
41
- hasCustomConfig: jest.fn().mockReturnValue(false),
42
- mergeConstraints: jest.fn().mockReturnValue({ custom: [], disabled: [] }),
43
- })),
37
+ // Mock effective-constraints(ADR-0001:check 经 getMergedConstraintsConfig 走生效集链路)
38
+ jest.mock('../../../core/effective-constraints', () => ({
39
+ getMergedConstraintsConfig: jest.fn().mockReturnValue({
40
+ ironLaws: {},
41
+ guidelines: {},
42
+ prompts: {},
43
+ custom: [],
44
+ disabled: [],
45
+ unknownIds: [],
46
+ }),
44
47
  }));
45
48
 
46
49
  // Mock chalk
@@ -5,7 +5,7 @@
5
5
  import { check, listLaws } from '../check';
6
6
  import * as fs from 'fs';
7
7
  import { constraintChecker } from '../../../core/constraints/checker';
8
- import { ProjectConfigLoader } from '../../../core/project-config-loader';
8
+ import { getMergedConstraintsConfig } from '../../../core/effective-constraints';
9
9
  import { execAsync } from '../../../utils/exec';
10
10
 
11
11
  // Mock fs
@@ -45,13 +45,16 @@ jest.mock('../../../core/constraints/checker', () => ({
45
45
  },
46
46
  }));
47
47
 
48
- // Mock ProjectConfigLoader
49
- jest.mock('../../../core/project-config-loader', () => ({
50
- ProjectConfigLoader: jest.fn().mockImplementation(() => ({
51
- load: jest.fn(),
52
- hasCustomConfig: jest.fn().mockReturnValue(false),
53
- mergeConstraints: jest.fn().mockReturnValue({ custom: [], disabled: [] }),
54
- })),
48
+ // Mock effective-constraints(ADR-0001:check 经 getMergedConstraintsConfig 走生效集链路)
49
+ jest.mock('../../../core/effective-constraints', () => ({
50
+ getMergedConstraintsConfig: jest.fn().mockReturnValue({
51
+ ironLaws: {},
52
+ guidelines: {},
53
+ prompts: {},
54
+ custom: [],
55
+ disabled: [],
56
+ unknownIds: [],
57
+ }),
55
58
  }));
56
59
 
57
60
  // Mock chalk
@@ -65,7 +68,7 @@ jest.mock('chalk', () => ({
65
68
 
66
69
  const mockFs = fs as jest.Mocked<typeof fs> & { readdirSync: jest.Mock };
67
70
  const mockChecker = constraintChecker as jest.Mocked<typeof constraintChecker>;
68
- const MockProjectConfigLoader = ProjectConfigLoader as jest.MockedClass<typeof ProjectConfigLoader>;
71
+ const mockGetMergedConfig = getMergedConstraintsConfig as jest.MockedFunction<typeof getMergedConstraintsConfig>;
69
72
  const mockExecAsync = execAsync as jest.MockedFunction<typeof execAsync>;
70
73
 
71
74
  describe('check command', () => {
@@ -73,6 +76,15 @@ describe('check command', () => {
73
76
 
74
77
  beforeEach(() => {
75
78
  jest.clearAllMocks();
79
+ // clearAllMocks 不清实现,显式恢复默认 merged config,避免用例间泄漏
80
+ mockGetMergedConfig.mockReturnValue({
81
+ ironLaws: {},
82
+ guidelines: {},
83
+ prompts: {},
84
+ custom: [],
85
+ disabled: [],
86
+ unknownIds: [],
87
+ });
76
88
  consoleSpy = jest.spyOn(console, 'log').mockImplementation();
77
89
  process.exitCode = 0;
78
90
  });
@@ -123,12 +135,14 @@ describe('check command', () => {
123
135
  });
124
136
 
125
137
  it('应该加载自定义约束', async () => {
126
- const mockLoader = {
127
- load: jest.fn(),
128
- hasCustomConfig: jest.fn().mockReturnValue(true),
129
- mergeConstraints: jest.fn().mockReturnValue({ custom: [{ id: 'custom', rule: 'test', message: 'test', level: 'iron_law', trigger: 'code_implementation', enforcement: 'checkpoint-required' }], disabled: ['disabled_constraint'] }),
130
- };
131
- (MockProjectConfigLoader as any).mockImplementation(() => mockLoader);
138
+ mockGetMergedConfig.mockReturnValue({
139
+ ironLaws: {},
140
+ guidelines: {},
141
+ prompts: {},
142
+ custom: ['custom'],
143
+ disabled: ['disabled_constraint'],
144
+ unknownIds: [],
145
+ });
132
146
 
133
147
  mockChecker.checkConstraints.mockResolvedValue({
134
148
  passed: true,
@@ -399,23 +413,6 @@ describe('check command', () => {
399
413
  expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('记录已足够'));
400
414
  });
401
415
 
402
- it('应该在绕过率高时提示查看详情', async () => {
403
- // 20 条记录,15 条 bypassed (75% > 30%)
404
- const traces = [
405
- ...Array(5).fill('{"result":"pass"}'),
406
- ...Array(15).fill('{"result":"bypassed"}'),
407
- ].join('\n');
408
- mockFs.existsSync.mockImplementation((p: any) => {
409
- if (p.includes('traces.log')) return true;
410
- if (p.includes('.state.json')) return false;
411
- return false;
412
- });
413
- mockFs.readFileSync.mockReturnValue(traces);
414
-
415
- await check({ preset: 'default', staged: false });
416
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('异常趋势'));
417
- });
418
-
419
416
  it('应该不重复显示已显示的提示', async () => {
420
417
  const traces = Array(50).fill('{"result":"pass"}').join('\n');
421
418
  mockFs.existsSync.mockReturnValue(true);
@@ -445,43 +442,6 @@ describe('check command', () => {
445
442
  expect(output).not.toContain('────────────────');
446
443
  });
447
444
 
448
- it('应该在绕过率低于 30% 时不提示', async () => {
449
- // 20 条记录,2 条 bypassed (10% < 30%)
450
- const traces = [
451
- ...Array(18).fill('{"result":"pass"}'),
452
- ...Array(2).fill('{"result":"bypassed"}'),
453
- ].join('\n');
454
- mockFs.existsSync.mockImplementation((p: any) => {
455
- if (p.includes('traces.log')) return true;
456
- if (p.includes('.state.json')) return false;
457
- return false;
458
- });
459
- mockFs.readFileSync.mockReturnValue(traces);
460
-
461
- await check({ preset: 'default', staged: false });
462
- const output = consoleSpy.mock.calls.map(c => c[0]).join('\n');
463
- expect(output).not.toContain('异常趋势');
464
- });
465
-
466
- it('应该处理无效 JSON trace 行', async () => {
467
- // 20 条记录,部分无效 JSON,部分 bypassed
468
- const traces = [
469
- ...Array(5).fill('invalid json'),
470
- ...Array(5).fill('{"result":"pass"}'),
471
- ...Array(10).fill('{"result":"bypassed"}'),
472
- ].join('\n');
473
- mockFs.existsSync.mockImplementation((p: any) => {
474
- if (p.includes('traces.log')) return true;
475
- if (p.includes('.state.json')) return false;
476
- return false;
477
- });
478
- mockFs.readFileSync.mockReturnValue(traces);
479
-
480
- await check({ preset: 'default', staged: false });
481
- // 15 条有效,10 条 bypassed,bypassRate = 10/20 = 0.5 > 0.3
482
- expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('异常趋势'));
483
- });
484
-
485
445
  it('应该保存状态文件当有提示时', async () => {
486
446
  const traces = Array(50).fill('{"result":"pass"}').join('\n');
487
447
  mockFs.existsSync.mockImplementation((p: any) => {
@@ -170,7 +170,7 @@ describe('buildConstraintsUsageReport', () => {
170
170
  const candidates = diagnoseRetireCandidates([
171
171
  {
172
172
  id: 'x', level: 'guideline',
173
- total: 60, pass: 0, fail: 0, skip: 60, bypassed: 0,
173
+ total: 60, pass: 0, fail: 0, skip: 60,
174
174
  evaluated: 0, failRate: 0,
175
175
  },
176
176
  ]);
@@ -2,7 +2,7 @@
2
2
  * knowledge 命令测试 — knowledgeAudit
3
3
  */
4
4
 
5
- import { knowledgeAudit, knowledgeStats, knowledgeHealth } from '../knowledge';
5
+ import { knowledgeAudit, knowledgeStats, knowledgeHealth, knowledgeSearch } from '../knowledge';
6
6
 
7
7
  // Mock chalk
8
8
  jest.mock('chalk', () => ({
@@ -233,3 +233,92 @@ describe('knowledgeHealth CLI', () => {
233
233
  expect(parsed.summary.staleEntries).toBe(1);
234
234
  });
235
235
  });
236
+
237
+ /**
238
+ * knowledgeSearch 回归测试 — harness#63
239
+ * bug:先按 token budget 截断再文本匹配,新条目(lastReferenced 为空、排序队尾)
240
+ * 在语料超过 budget 时永远进不了匹配阶段。
241
+ */
242
+ describe('knowledgeSearch CLI (harness#63)', () => {
243
+ const fs = require('fs');
244
+ const os = require('os');
245
+ const path = require('path');
246
+ const { FileKnowledgeStore } = require('../../../knowledge/store');
247
+
248
+ let tmpProject: string;
249
+ let knowledgeDir: string;
250
+ let consoleSpy: jest.SpyInstance;
251
+
252
+ const FILLER_COUNT = 25; // 25 × ~800 tokens ≈ 20000 > maxTokens 10000
253
+ const TARGET_ID = 'PIT-020';
254
+
255
+ function makeEntry(overrides: Record<string, any>): any {
256
+ return {
257
+ id: 'X-000',
258
+ type: 'pitfall',
259
+ title: '条目',
260
+ content: '内容',
261
+ maturity: 'proven',
262
+ layer: 'project',
263
+ created: '2026-08-01T00:00:00.000Z',
264
+ lastReferenced: '2026-08-01T00:00:00.000Z',
265
+ contributors: [],
266
+ projects: [],
267
+ tags: [],
268
+ applicablePhases: [],
269
+ sourceReferences: [],
270
+ referencedBy: [],
271
+ executionResults: [],
272
+ consumptionMode: 'reference',
273
+ origin: 'agent',
274
+ ...overrides,
275
+ };
276
+ }
277
+
278
+ beforeEach(() => {
279
+ tmpProject = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-k63-'));
280
+ knowledgeDir = path.join(tmpProject, '.harness', 'knowledge');
281
+ fs.mkdirSync(knowledgeDir, { recursive: true });
282
+ consoleSpy = jest.spyOn(console, 'log').mockImplementation();
283
+
284
+ const store = new FileKnowledgeStore({ baseDir: knowledgeDir });
285
+ // 高成熟度 + 有 lastReferenced 的填充条目排在前面,吃满 token budget
286
+ for (let i = 0; i < FILLER_COUNT; i++) {
287
+ store.save(makeEntry({
288
+ id: `FILL-${String(i).padStart(3, '0')}`,
289
+ title: `填充条目 ${i}`,
290
+ content: '填'.repeat(399) + '共同词',
291
+ }));
292
+ }
293
+ // 目标条目:新条目,draft + lastReferenced 为空,排在队尾
294
+ store.save(makeEntry({
295
+ id: TARGET_ID,
296
+ title: '新条目',
297
+ maturity: 'draft',
298
+ lastReferenced: '',
299
+ content: 'autolink 相关条目 共同词',
300
+ }));
301
+ });
302
+
303
+ afterEach(() => {
304
+ consoleSpy.mockRestore();
305
+ fs.rmSync(tmpProject, { recursive: true, force: true });
306
+ });
307
+
308
+ async function searchJson(query: string, limit: number): Promise<any> {
309
+ await knowledgeSearch(query, { projectPath: tmpProject, json: true, limit });
310
+ const output = consoleSpy.mock.calls.map((c: any[]) => c[0]).join('\n');
311
+ return JSON.parse(output);
312
+ }
313
+
314
+ it('语料超过 token budget 时,排在队尾的新条目仍可被搜到', async () => {
315
+ const result = await searchJson('autolink', 200);
316
+ expect(result.total).toBe(1);
317
+ expect(result.entries[0].id).toBe(TARGET_ID);
318
+ });
319
+
320
+ it('超高频关键词的返回数 = 实际匹配数(截断只发生在匹配之后)', async () => {
321
+ const result = await searchJson('共同词', 200);
322
+ expect(result.total).toBe(FILLER_COUNT + 1);
323
+ });
324
+ });
@@ -51,11 +51,10 @@ describe('命令注册表闭环', () => {
51
51
  });
52
52
 
53
53
  it('全部实现引用可解析(module 存在且 export 是函数)', () => {
54
- const refs = collectRefs(COMMAND_DEFINITIONS);
55
- for (const def of GATE_DEFINITIONS) {
56
- refs.push(def.cli.action);
57
- for (const entry of Object.values(def.cli.subcommands || {})) refs.push(entry);
58
- }
54
+ const refs = collectRefs([
55
+ ...COMMAND_DEFINITIONS,
56
+ ...GATE_DEFINITIONS.map(d => d.cli),
57
+ ]);
59
58
  expect(refs.length).toBeGreaterThan(0);
60
59
 
61
60
  for (const ref of refs) {
@@ -107,7 +106,10 @@ describe('命令注册表闭环', () => {
107
106
  }
108
107
  for (const child of def.children || []) walk(child);
109
108
  };
110
- for (const def of COMMAND_DEFINITIONS) walk(def);
109
+ for (const def of [
110
+ ...COMMAND_DEFINITIONS,
111
+ ...GATE_DEFINITIONS.map(d => d.cli),
112
+ ]) walk(def);
111
113
  // sync-docs --check 失败路径确实会请求退出
112
114
  expect(exitSpy).toHaveBeenCalled();
113
115
  } finally {
@@ -81,7 +81,7 @@ describe('status command - 补充覆盖', () => {
81
81
  ];
82
82
  const mockAnalyze = {
83
83
  summarize: jest.fn().mockReturnValue([
84
- { constraintId: 'no_bypass_checkpoint', level: 'iron_law', passRate: 0.2, totalChecks: 10, bypassRate: 0.1 },
84
+ { constraintId: 'no_bypass_checkpoint', level: 'iron_law', passRate: 0.2, failRate: 0.8, totalChecks: 10 },
85
85
  ]),
86
86
  detectAnomalies: jest.fn().mockReturnValue(mockAnomalies),
87
87
  };
@@ -119,8 +119,8 @@ describe('status command - 补充覆盖', () => {
119
119
  mockFs.readFileSync.mockReturnValue(mockTraces.map(t => JSON.stringify(t)).join('\n'));
120
120
 
121
121
  const mockSummaries = [
122
- { constraintId: 'no_bypass_checkpoint', level: 'iron_law', passRate: 1, totalChecks: 10, bypassRate: 0 },
123
- { constraintId: 'no_completion_without_verification', level: 'iron_law', passRate: 0.8, totalChecks: 5, bypassRate: 0 },
122
+ { constraintId: 'no_bypass_checkpoint', level: 'iron_law', passRate: 1, failRate: 0, totalChecks: 10 },
123
+ { constraintId: 'no_completion_without_verification', level: 'iron_law', passRate: 0.8, failRate: 0.2, totalChecks: 5 },
124
124
  ];
125
125
  const mockAnalyze = {
126
126
  summarize: jest.fn().mockReturnValue(mockSummaries),
@@ -141,7 +141,7 @@ describe('status command - 补充覆盖', () => {
141
141
  mockFs.readFileSync.mockReturnValue(mockTraces.map(t => JSON.stringify(t)).join('\n'));
142
142
 
143
143
  const mockSummaries = [
144
- { constraintId: 'capability_sync', level: 'guideline', passRate: 0.9, totalChecks: 20, bypassRate: 0.1 },
144
+ { constraintId: 'capability_sync', level: 'guideline', passRate: 0.9, failRate: 0.1, totalChecks: 20 },
145
145
  ];
146
146
  const mockAnalyze = {
147
147
  summarize: jest.fn().mockReturnValue(mockSummaries),
@@ -164,8 +164,8 @@ describe('status command - 补充覆盖', () => {
164
164
  mockFs.readFileSync.mockReturnValue(mockTraces.map(t => JSON.stringify(t)).join('\n'));
165
165
 
166
166
  const mockSummaries = [
167
- { constraintId: 'no_bypass_checkpoint', level: 'iron_law', passRate: 1, totalChecks: 10, bypassRate: 0 },
168
- { constraintId: 'capability_sync', level: 'guideline', passRate: 0.9, totalChecks: 20, bypassRate: 0.1 },
167
+ { constraintId: 'no_bypass_checkpoint', level: 'iron_law', passRate: 1, failRate: 0, totalChecks: 10 },
168
+ { constraintId: 'capability_sync', level: 'guideline', passRate: 0.9, failRate: 0.1, totalChecks: 20 },
169
169
  ];
170
170
  const mockAnalyze = {
171
171
  summarize: jest.fn().mockReturnValue(mockSummaries),
@@ -87,7 +87,7 @@ describe('status command', () => {
87
87
  mockFs.readFileSync.mockReturnValue(mockTraces.map(t => JSON.stringify(t)).join('\n'));
88
88
 
89
89
  const mockSummarize = jest.fn().mockReturnValue([
90
- { constraintId: 'test1', level: 'iron_law', passRate: 1, totalChecks: 1, bypassRate: 0 },
90
+ { constraintId: 'test1', level: 'iron_law', passRate: 1, failRate: 0, totalChecks: 1 },
91
91
  ]);
92
92
  const mockAnalyze = {
93
93
  summarize: mockSummarize,
@@ -106,7 +106,7 @@ describe('status command', () => {
106
106
  mockFs.readFileSync.mockReturnValue(mockTraces.map(t => JSON.stringify(t)).join('\n'));
107
107
 
108
108
  const mockSummarize = jest.fn().mockReturnValue([
109
- { constraintId: 'no_bypass_checkpoint', level: 'iron_law', passRate: 1, totalChecks: 5, bypassRate: 0 },
109
+ { constraintId: 'no_bypass_checkpoint', level: 'iron_law', passRate: 1, failRate: 0, totalChecks: 5 },
110
110
  ]);
111
111
  const mockAnalyze = {
112
112
  summarize: mockSummarize,
@@ -131,7 +131,7 @@ describe('status command', () => {
131
131
  ];
132
132
  const mockAnalyze = {
133
133
  summarize: jest.fn().mockReturnValue([
134
- { constraintId: 'test1', level: 'iron_law', passRate: 0.2, totalChecks: 5, bypassRate: 0 },
134
+ { constraintId: 'test1', level: 'iron_law', passRate: 0.2, failRate: 0.8, totalChecks: 5 },
135
135
  ]),
136
136
  detectAnomalies: jest.fn().mockReturnValue(mockAnomalies),
137
137
  };
@@ -150,7 +150,7 @@ describe('status command', () => {
150
150
  mockFs.readFileSync.mockReturnValue(mockTraces.map(t => JSON.stringify(t)).join('\n'));
151
151
 
152
152
  const mockSummarize = jest.fn().mockReturnValue([
153
- { constraintId: 'test1', level: 'iron_law', passRate: 0.8, totalChecks: 10, bypassRate: 0.1 },
153
+ { constraintId: 'test1', level: 'iron_law', passRate: 0.8, failRate: 0.2, totalChecks: 10 },
154
154
  ]);
155
155
  const mockAnalyze = {
156
156
  summarize: mockSummarize,
@@ -184,7 +184,7 @@ describe('status command', () => {
184
184
 
185
185
  const mockAnalyze = {
186
186
  summarize: jest.fn().mockReturnValue([
187
- { constraintId: 'test_guide', level: 'guideline', passRate: 0.9, totalChecks: 10, bypassRate: 0 },
187
+ { constraintId: 'test_guide', level: 'guideline', passRate: 0.9, failRate: 0.1, totalChecks: 10 },
188
188
  ]),
189
189
  detectAnomalies: jest.fn().mockReturnValue([]),
190
190
  };
@@ -276,7 +276,7 @@ describe('status command', () => {
276
276
 
277
277
  const mockAnalyze = {
278
278
  summarize: jest.fn().mockReturnValue([
279
- { constraintId: 'test_guide', level: 'guideline', passRate: 0.6, totalChecks: 10, bypassRate: 0.1 },
279
+ { constraintId: 'test_guide', level: 'guideline', passRate: 0.6, failRate: 0.4, totalChecks: 10 },
280
280
  ]),
281
281
  detectAnomalies: jest.fn().mockReturnValue([]),
282
282
  };