@dommaker/harness 1.1.0 → 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 (349) hide show
  1. package/CHANGELOG.md +19 -2
  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.d.ts.map +1 -1
  21. package/dist/cli/commands/status.js +2 -11
  22. package/dist/cli/commands/status.js.map +1 -1
  23. package/dist/context/index.d.ts +9 -6
  24. package/dist/context/index.d.ts.map +1 -1
  25. package/dist/context/index.js +18 -20
  26. package/dist/context/index.js.map +1 -1
  27. package/dist/core/constraints/capabilities-parser.d.ts +3 -2
  28. package/dist/core/constraints/capabilities-parser.d.ts.map +1 -1
  29. package/dist/core/constraints/capabilities-parser.js +25 -47
  30. package/dist/core/constraints/capabilities-parser.js.map +1 -1
  31. package/dist/core/constraints/checker.d.ts +32 -33
  32. package/dist/core/constraints/checker.d.ts.map +1 -1
  33. package/dist/core/constraints/checker.js +38 -128
  34. package/dist/core/constraints/checker.js.map +1 -1
  35. package/dist/core/constraints/checkers/index.d.ts +2 -1
  36. package/dist/core/constraints/checkers/index.d.ts.map +1 -1
  37. package/dist/core/constraints/checkers/index.js +3 -0
  38. package/dist/core/constraints/checkers/index.js.map +1 -1
  39. package/dist/core/constraints/checkers/types.d.ts +25 -0
  40. package/dist/core/constraints/checkers/types.d.ts.map +1 -1
  41. package/dist/core/constraints/checkers/types.js +24 -0
  42. package/dist/core/constraints/checkers/types.js.map +1 -1
  43. package/dist/core/constraints/definitions/guidelines.d.ts.map +1 -1
  44. package/dist/core/constraints/definitions/guidelines.js +0 -2
  45. package/dist/core/constraints/definitions/guidelines.js.map +1 -1
  46. package/dist/core/constraints/definitions/prompts.d.ts.map +1 -1
  47. package/dist/core/constraints/definitions/prompts.js +0 -5
  48. package/dist/core/constraints/definitions/prompts.js.map +1 -1
  49. package/dist/core/constraints/index.d.ts +1 -2
  50. package/dist/core/constraints/index.d.ts.map +1 -1
  51. package/dist/core/constraints/index.js +1 -7
  52. package/dist/core/constraints/index.js.map +1 -1
  53. package/dist/core/constraints/usage-report.d.ts +1 -2
  54. package/dist/core/constraints/usage-report.d.ts.map +1 -1
  55. package/dist/core/constraints/usage-report.js +2 -5
  56. package/dist/core/constraints/usage-report.js.map +1 -1
  57. package/dist/core/effective-constraints.d.ts +24 -4
  58. package/dist/core/effective-constraints.d.ts.map +1 -1
  59. package/dist/core/effective-constraints.js +28 -7
  60. package/dist/core/effective-constraints.js.map +1 -1
  61. package/dist/core/effective-set.d.ts +30 -0
  62. package/dist/core/effective-set.d.ts.map +1 -0
  63. package/dist/core/effective-set.js +35 -0
  64. package/dist/core/effective-set.js.map +1 -0
  65. package/dist/core/index.d.ts +13 -6
  66. package/dist/core/index.d.ts.map +1 -1
  67. package/dist/core/index.js +44 -21
  68. package/dist/core/index.js.map +1 -1
  69. package/dist/core/project-config-loader.d.ts +3 -6
  70. package/dist/core/project-config-loader.d.ts.map +1 -1
  71. package/dist/core/project-config-loader.js +47 -61
  72. package/dist/core/project-config-loader.js.map +1 -1
  73. package/dist/failure/constraint-handler.d.ts +1 -1
  74. package/dist/failure/constraint-handler.js +1 -1
  75. package/dist/gates/checker-gate.d.ts +1 -4
  76. package/dist/gates/checker-gate.d.ts.map +1 -1
  77. package/dist/gates/checker-gate.js +3 -11
  78. package/dist/gates/checker-gate.js.map +1 -1
  79. package/dist/gates/definitions.d.ts +9 -38
  80. package/dist/gates/definitions.d.ts.map +1 -1
  81. package/dist/gates/definitions.js +24 -13
  82. package/dist/gates/definitions.js.map +1 -1
  83. package/dist/gates/effective-gates.d.ts.map +1 -1
  84. package/dist/gates/effective-gates.js +14 -18
  85. package/dist/gates/effective-gates.js.map +1 -1
  86. package/dist/gates/index.d.ts +1 -1
  87. package/dist/gates/index.d.ts.map +1 -1
  88. package/dist/gates/index.js.map +1 -1
  89. package/dist/hooks/bootstrap.d.ts.map +1 -1
  90. package/dist/hooks/bootstrap.js +0 -3
  91. package/dist/hooks/bootstrap.js.map +1 -1
  92. package/dist/index.d.ts +43 -53
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +180 -138
  95. package/dist/index.js.map +1 -1
  96. package/dist/knowledge/query.d.ts +15 -0
  97. package/dist/knowledge/query.d.ts.map +1 -1
  98. package/dist/knowledge/query.js +23 -0
  99. package/dist/knowledge/query.js.map +1 -1
  100. package/dist/monitoring/analyzer-base.d.ts +0 -4
  101. package/dist/monitoring/analyzer-base.d.ts.map +1 -1
  102. package/dist/monitoring/analyzer-base.js +0 -21
  103. package/dist/monitoring/analyzer-base.js.map +1 -1
  104. package/dist/monitoring/index.d.ts +6 -12
  105. package/dist/monitoring/index.d.ts.map +1 -1
  106. package/dist/monitoring/index.js +13 -29
  107. package/dist/monitoring/index.js.map +1 -1
  108. package/dist/monitoring/trace-analyzer.d.ts.map +1 -1
  109. package/dist/monitoring/trace-analyzer.js +2 -68
  110. package/dist/monitoring/trace-analyzer.js.map +1 -1
  111. package/dist/monitoring/traces.d.ts +2 -6
  112. package/dist/monitoring/traces.d.ts.map +1 -1
  113. package/dist/monitoring/traces.js +0 -14
  114. package/dist/monitoring/traces.js.map +1 -1
  115. package/dist/presets/index.d.ts +2 -2
  116. package/dist/presets/index.d.ts.map +1 -1
  117. package/dist/presets/index.js +3 -4
  118. package/dist/presets/index.js.map +1 -1
  119. package/dist/presets/standard.d.ts +10 -22
  120. package/dist/presets/standard.d.ts.map +1 -1
  121. package/dist/presets/standard.js +15 -75
  122. package/dist/presets/standard.js.map +1 -1
  123. package/dist/types/constraint.d.ts +1 -29
  124. package/dist/types/constraint.d.ts.map +1 -1
  125. package/dist/types/constraint.js +1 -1
  126. package/dist/types/constraint.js.map +1 -1
  127. package/dist/types/index.d.ts +0 -3
  128. package/dist/types/index.d.ts.map +1 -1
  129. package/dist/types/index.js +0 -4
  130. package/dist/types/index.js.map +1 -1
  131. package/dist/types/project-config.d.ts +4 -8
  132. package/dist/types/project-config.d.ts.map +1 -1
  133. package/dist/types/trace.d.ts +9 -22
  134. package/dist/types/trace.d.ts.map +1 -1
  135. package/package.json +2 -2
  136. package/src/CONTEXT.md +5 -7
  137. package/src/__tests__/checker-extra.test.ts +80 -139
  138. package/src/__tests__/checker.test.ts +0 -376
  139. package/src/__tests__/project-config-loader-extra.test.ts +42 -29
  140. package/src/__tests__/public-exports.test.ts +138 -0
  141. package/src/__tests__/trace-analyzer-extra.test.ts +6 -86
  142. package/src/__tests__/trace-analyzer.test.ts +4 -5
  143. package/src/__tests__/trace-collector.test.ts +0 -11
  144. package/src/__tests__/traces.test.ts +3 -22
  145. package/src/cli/commands/CONTEXT.md +2 -2
  146. package/src/cli/commands/__tests__/check-skip-output.test.ts +10 -7
  147. package/src/cli/commands/__tests__/check.test.ts +29 -69
  148. package/src/cli/commands/__tests__/constraints-report.test.ts +1 -1
  149. package/src/cli/commands/__tests__/knowledge.test.ts +90 -1
  150. package/src/cli/commands/__tests__/registry.test.ts +8 -6
  151. package/src/cli/commands/__tests__/status-extra.test.ts +6 -28
  152. package/src/cli/commands/__tests__/status.test.ts +6 -21
  153. package/src/cli/commands/check.ts +8 -34
  154. package/src/cli/commands/definitions.ts +2 -0
  155. package/src/cli/commands/init.ts +6 -37
  156. package/src/cli/commands/knowledge.ts +1 -16
  157. package/src/cli/commands/report.ts +0 -2
  158. package/src/cli/commands/status.ts +2 -12
  159. package/src/context/index.ts +29 -6
  160. package/src/core/CONTEXT.md +4 -3
  161. package/src/core/__tests__/effective-set.test.ts +80 -0
  162. package/src/core/constraints/capabilities-parser.ts +43 -49
  163. package/src/core/constraints/checker.ts +56 -147
  164. package/src/core/constraints/checkers/index.ts +2 -1
  165. package/src/core/constraints/checkers/types.ts +42 -0
  166. package/src/core/constraints/definitions/guidelines.ts +0 -2
  167. package/src/core/constraints/definitions/prompts.ts +0 -5
  168. package/src/core/constraints/index.ts +2 -17
  169. package/src/core/constraints/usage-report.ts +5 -8
  170. package/src/core/effective-constraints.ts +35 -7
  171. package/src/core/effective-set.ts +56 -0
  172. package/src/core/index.ts +80 -6
  173. package/src/core/project-config-loader.ts +53 -68
  174. package/src/failure/CONTEXT.md +1 -1
  175. package/src/failure/constraint-handler.ts +1 -1
  176. package/src/gates/CONTEXT.md +3 -3
  177. package/src/gates/checker-gate.ts +4 -12
  178. package/src/gates/definitions.ts +27 -50
  179. package/src/gates/effective-gates.ts +14 -21
  180. package/src/gates/index.ts +1 -1
  181. package/src/hooks/bootstrap.ts +0 -3
  182. package/src/index.ts +384 -137
  183. package/src/knowledge/CONTEXT.md +2 -2
  184. package/src/knowledge/__tests__/query.test.ts +64 -0
  185. package/src/knowledge/query.ts +28 -0
  186. package/src/monitoring/CONTEXT.md +7 -13
  187. package/src/monitoring/__tests__/traces.test.ts +0 -10
  188. package/src/monitoring/analyzer-base.ts +0 -22
  189. package/src/monitoring/index.ts +6 -12
  190. package/src/monitoring/trace-analyzer.ts +2 -73
  191. package/src/monitoring/traces.ts +2 -22
  192. package/src/presets/__tests__/standard.test.ts +48 -69
  193. package/src/presets/index.ts +3 -5
  194. package/src/presets/standard.ts +14 -79
  195. package/src/spec/CONTEXT.md +5 -13
  196. package/src/types/constraint.ts +1 -51
  197. package/src/types/index.ts +0 -12
  198. package/src/types/project-config.ts +4 -10
  199. package/src/types/trace.ts +9 -34
  200. package/dist/core/constraints/interceptor.d.ts +0 -38
  201. package/dist/core/constraints/interceptor.d.ts.map +0 -1
  202. package/dist/core/constraints/interceptor.js +0 -166
  203. package/dist/core/constraints/interceptor.js.map +0 -1
  204. package/dist/dashboard/data.d.ts +0 -31
  205. package/dist/dashboard/data.d.ts.map +0 -1
  206. package/dist/dashboard/data.js +0 -81
  207. package/dist/dashboard/data.js.map +0 -1
  208. package/dist/dashboard/index.d.ts +0 -4
  209. package/dist/dashboard/index.d.ts.map +0 -1
  210. package/dist/dashboard/index.js +0 -20
  211. package/dist/dashboard/index.js.map +0 -1
  212. package/dist/dashboard/stats.d.ts +0 -20
  213. package/dist/dashboard/stats.d.ts.map +0 -1
  214. package/dist/dashboard/stats.js +0 -115
  215. package/dist/dashboard/stats.js.map +0 -1
  216. package/dist/dashboard/types.d.ts +0 -110
  217. package/dist/dashboard/types.d.ts.map +0 -1
  218. package/dist/dashboard/types.js +0 -8
  219. package/dist/dashboard/types.js.map +0 -1
  220. package/dist/monitoring/constraint-doctor.d.ts +0 -82
  221. package/dist/monitoring/constraint-doctor.d.ts.map +0 -1
  222. package/dist/monitoring/constraint-doctor.js +0 -191
  223. package/dist/monitoring/constraint-doctor.js.map +0 -1
  224. package/dist/monitoring/diagnosis-rules.d.ts +0 -18
  225. package/dist/monitoring/diagnosis-rules.d.ts.map +0 -1
  226. package/dist/monitoring/diagnosis-rules.js +0 -119
  227. package/dist/monitoring/diagnosis-rules.js.map +0 -1
  228. package/dist/monitoring/knowledge-doctor.d.ts +0 -78
  229. package/dist/monitoring/knowledge-doctor.d.ts.map +0 -1
  230. package/dist/monitoring/knowledge-doctor.js +0 -266
  231. package/dist/monitoring/knowledge-doctor.js.map +0 -1
  232. package/dist/monitoring/knowledge-evolver.d.ts +0 -72
  233. package/dist/monitoring/knowledge-evolver.d.ts.map +0 -1
  234. package/dist/monitoring/knowledge-evolver.js +0 -205
  235. package/dist/monitoring/knowledge-evolver.js.map +0 -1
  236. package/dist/monitoring/performance-analyzer.d.ts +0 -92
  237. package/dist/monitoring/performance-analyzer.d.ts.map +0 -1
  238. package/dist/monitoring/performance-analyzer.js +0 -343
  239. package/dist/monitoring/performance-analyzer.js.map +0 -1
  240. package/dist/monitoring/performance-collector.d.ts +0 -103
  241. package/dist/monitoring/performance-collector.d.ts.map +0 -1
  242. package/dist/monitoring/performance-collector.js +0 -298
  243. package/dist/monitoring/performance-collector.js.map +0 -1
  244. package/dist/safety/index.d.ts +0 -6
  245. package/dist/safety/index.d.ts.map +0 -1
  246. package/dist/safety/index.js +0 -22
  247. package/dist/safety/index.js.map +0 -1
  248. package/dist/safety/input-guardrail.d.ts +0 -36
  249. package/dist/safety/input-guardrail.d.ts.map +0 -1
  250. package/dist/safety/input-guardrail.js +0 -118
  251. package/dist/safety/input-guardrail.js.map +0 -1
  252. package/dist/safety/output-guardrail.d.ts +0 -39
  253. package/dist/safety/output-guardrail.d.ts.map +0 -1
  254. package/dist/safety/output-guardrail.js +0 -147
  255. package/dist/safety/output-guardrail.js.map +0 -1
  256. package/dist/safety/sandbox.d.ts +0 -45
  257. package/dist/safety/sandbox.d.ts.map +0 -1
  258. package/dist/safety/sandbox.js +0 -134
  259. package/dist/safety/sandbox.js.map +0 -1
  260. package/dist/safety/tool-guardrail.d.ts +0 -51
  261. package/dist/safety/tool-guardrail.d.ts.map +0 -1
  262. package/dist/safety/tool-guardrail.js +0 -147
  263. package/dist/safety/tool-guardrail.js.map +0 -1
  264. package/dist/safety/types.d.ts +0 -104
  265. package/dist/safety/types.d.ts.map +0 -1
  266. package/dist/safety/types.js +0 -6
  267. package/dist/safety/types.js.map +0 -1
  268. package/dist/spec/annotation-checker.d.ts +0 -47
  269. package/dist/spec/annotation-checker.d.ts.map +0 -1
  270. package/dist/spec/annotation-checker.js +0 -279
  271. package/dist/spec/annotation-checker.js.map +0 -1
  272. package/dist/types/enforcement.d.ts +0 -42
  273. package/dist/types/enforcement.d.ts.map +0 -1
  274. package/dist/types/enforcement.js +0 -6
  275. package/dist/types/enforcement.js.map +0 -1
  276. package/dist/types/monitoring-types.d.ts +0 -53
  277. package/dist/types/monitoring-types.d.ts.map +0 -1
  278. package/dist/types/monitoring-types.js +0 -10
  279. package/dist/types/monitoring-types.js.map +0 -1
  280. package/dist/types/performance.d.ts +0 -204
  281. package/dist/types/performance.d.ts.map +0 -1
  282. package/dist/types/performance.js +0 -12
  283. package/dist/types/performance.js.map +0 -1
  284. package/dist/verification/index.d.ts +0 -4
  285. package/dist/verification/index.d.ts.map +0 -1
  286. package/dist/verification/index.js +0 -20
  287. package/dist/verification/index.js.map +0 -1
  288. package/dist/verification/loop.d.ts +0 -30
  289. package/dist/verification/loop.d.ts.map +0 -1
  290. package/dist/verification/loop.js +0 -114
  291. package/dist/verification/loop.js.map +0 -1
  292. package/dist/verification/rules-based.d.ts +0 -40
  293. package/dist/verification/rules-based.d.ts.map +0 -1
  294. package/dist/verification/rules-based.js +0 -130
  295. package/dist/verification/rules-based.js.map +0 -1
  296. package/dist/verification/types.d.ts +0 -69
  297. package/dist/verification/types.d.ts.map +0 -1
  298. package/dist/verification/types.js +0 -6
  299. package/dist/verification/types.js.map +0 -1
  300. package/src/__tests__/annotation-checker.test.ts +0 -183
  301. package/src/__tests__/constraint-doctor.test.ts +0 -271
  302. package/src/__tests__/doctor-extra.test.ts +0 -155
  303. package/src/__tests__/extend-exceptions.test.ts +0 -149
  304. package/src/__tests__/interceptor.test.ts +0 -89
  305. package/src/__tests__/performance-analyzer.test.ts +0 -499
  306. package/src/__tests__/performance-collector.test.ts +0 -276
  307. package/src/__tests__/presets.test.ts +0 -65
  308. package/src/core/constraints/__tests__/interceptor.test.ts +0 -253
  309. package/src/core/constraints/interceptor.ts +0 -214
  310. package/src/dashboard/CONTEXT.md +0 -21
  311. package/src/dashboard/__tests__/data.test.ts +0 -111
  312. package/src/dashboard/__tests__/stats.test.ts +0 -159
  313. package/src/dashboard/data.ts +0 -103
  314. package/src/dashboard/index.ts +0 -3
  315. package/src/dashboard/stats.ts +0 -127
  316. package/src/dashboard/types.ts +0 -130
  317. package/src/monitoring/__tests__/knowledge-doctor.test.ts +0 -278
  318. package/src/monitoring/__tests__/knowledge-evolver.test.ts +0 -368
  319. package/src/monitoring/__tests__/performance-analyzer.test.ts +0 -137
  320. package/src/monitoring/__tests__/performance-collector.test.ts +0 -331
  321. package/src/monitoring/constraint-doctor.ts +0 -239
  322. package/src/monitoring/diagnosis-rules.ts +0 -132
  323. package/src/monitoring/knowledge-doctor.ts +0 -322
  324. package/src/monitoring/knowledge-evolver.ts +0 -289
  325. package/src/monitoring/performance-analyzer.ts +0 -400
  326. package/src/monitoring/performance-collector.ts +0 -326
  327. package/src/safety/CONTEXT.md +0 -23
  328. package/src/safety/__tests__/input-guardrail.test.ts +0 -105
  329. package/src/safety/__tests__/output-guardrail.test.ts +0 -108
  330. package/src/safety/__tests__/sandbox.test.ts +0 -158
  331. package/src/safety/__tests__/tool-guardrail.test.ts +0 -127
  332. package/src/safety/index.ts +0 -5
  333. package/src/safety/input-guardrail.ts +0 -133
  334. package/src/safety/output-guardrail.ts +0 -170
  335. package/src/safety/sandbox.ts +0 -148
  336. package/src/safety/tool-guardrail.ts +0 -176
  337. package/src/safety/types.ts +0 -124
  338. package/src/spec/__tests__/annotation-checker.test.ts +0 -294
  339. package/src/spec/annotation-checker.ts +0 -320
  340. package/src/types/enforcement.ts +0 -48
  341. package/src/types/monitoring-types.ts +0 -68
  342. package/src/types/performance.ts +0 -295
  343. package/src/verification/CONTEXT.md +0 -23
  344. package/src/verification/__tests__/loop.test.ts +0 -303
  345. package/src/verification/__tests__/rules-based.test.ts +0 -240
  346. package/src/verification/index.ts +0 -3
  347. package/src/verification/loop.ts +0 -137
  348. package/src/verification/rules-based.ts +0 -152
  349. package/src/verification/types.ts +0 -81
@@ -1,276 +0,0 @@
1
- /**
2
- * PerformanceCollector 测试
3
- */
4
-
5
- import { describe, it, expect, beforeAll, afterAll, beforeEach } from '@jest/globals';
6
- import { PerformanceCollector } from '../monitoring/performance-collector';
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
-
10
- describe('PerformanceCollector', () => {
11
- const tempDir = path.join(process.cwd(), 'temp-test-perf');
12
- const logFile = path.join(tempDir, 'performance.log');
13
- let collector: PerformanceCollector;
14
-
15
- beforeAll(() => {
16
- fs.mkdirSync(tempDir, { recursive: true });
17
- });
18
-
19
- afterAll(() => {
20
- try {
21
- fs.rmSync(tempDir, { recursive: true, force: true });
22
- } catch {
23
- // ignore
24
- }
25
- });
26
-
27
- beforeEach(() => {
28
- fs.writeFileSync(logFile, '');
29
- collector = new PerformanceCollector({ logFile, enabled: true });
30
- });
31
-
32
- describe('record', () => {
33
- it('应该记录性能数据', () => {
34
- collector.record({
35
- operation: 'test_op',
36
- timestamp: Date.now(),
37
- duration: 100,
38
- result: 'ok',
39
- });
40
-
41
- const content = fs.readFileSync(logFile, 'utf-8');
42
- expect(content).toContain('test_op');
43
- expect(content).toContain('ok');
44
- });
45
-
46
- it('禁用时应该不记录', () => {
47
- const disabledCollector = new PerformanceCollector({
48
- logFile,
49
- enabled: false,
50
- });
51
-
52
- disabledCollector.record({
53
- operation: 'test',
54
- timestamp: Date.now(),
55
- duration: 100,
56
- result: 'ok',
57
- });
58
-
59
- const content = fs.readFileSync(logFile, 'utf-8');
60
- expect(content).toBe('');
61
- });
62
- });
63
-
64
- describe('recordOk', () => {
65
- it('应该记录正常执行', () => {
66
- collector.recordOk('extract', 150);
67
-
68
- const content = fs.readFileSync(logFile, 'utf-8');
69
- expect(content).toContain('extract');
70
- expect(content).toContain('150');
71
- expect(content).toContain('ok');
72
- });
73
-
74
- it('应该支持元数据', () => {
75
- collector.recordOk('extract', 150, { files: 10 });
76
-
77
- const content = fs.readFileSync(logFile, 'utf-8');
78
- expect(content).toContain('files');
79
- });
80
- });
81
-
82
- describe('recordExceeded', () => {
83
- it('应该记录超阈值执行', () => {
84
- collector.recordExceeded('invokeAgent', 35000, 30000);
85
-
86
- const content = fs.readFileSync(logFile, 'utf-8');
87
- expect(content).toContain('invokeAgent');
88
- expect(content).toContain('exceeded');
89
- expect(content).toContain('35000');
90
- });
91
- });
92
-
93
- describe('read', () => {
94
- it('应该读取性能数据', () => {
95
- collector.recordOk('op1', 100);
96
- collector.recordOk('op2', 200);
97
-
98
- const traces = collector.read();
99
- expect(traces.length).toBe(2);
100
- });
101
-
102
- it('空文件应该返回空数组', () => {
103
- fs.writeFileSync(logFile, '');
104
- const traces = collector.read();
105
- expect(traces).toEqual([]);
106
- });
107
- });
108
-
109
- describe('getStats', () => {
110
- it('应该返回统计信息', () => {
111
- collector.recordOk('op1', 100);
112
- collector.recordOk('op2', 200);
113
- collector.recordExceeded('op3', 500, 400);
114
-
115
- const stats = collector.getStats();
116
-
117
- expect(stats.totalRecords).toBe(3);
118
- });
119
-
120
- it('应该正确读取数据', () => {
121
- collector.recordOk('op1', 100);
122
- collector.recordOk('op2', 200);
123
-
124
- const traces = collector.read();
125
-
126
- expect(traces.length).toBe(2);
127
- });
128
-
129
- it('文件不存在时应该返回空统计', () => {
130
- fs.unlinkSync(logFile);
131
- const tmpFile = path.join(require('os').tmpdir(), 'harness-test-nonexistent', 'perf.log');
132
- const newCollector = new PerformanceCollector({ logFile: tmpFile });
133
-
134
- const stats = newCollector.getStats();
135
-
136
- expect(stats.fileExists).toBe(false);
137
- expect(stats.totalRecords).toBe(0);
138
- });
139
- });
140
-
141
- describe('recordError', () => {
142
- it('应该记录错误', () => {
143
- collector.recordError('failing-op', 100, 'Something went wrong');
144
-
145
- const content = fs.readFileSync(logFile, 'utf-8');
146
- expect(content).toContain('error');
147
- expect(content).toContain('Something went wrong');
148
- });
149
-
150
- it('应该支持 Error 对象', () => {
151
- collector.recordError('failing-op', 100, new Error('Test error'));
152
-
153
- const content = fs.readFileSync(logFile, 'utf-8');
154
- expect(content).toContain('Test error');
155
- });
156
-
157
- it('应该支持元数据', () => {
158
- collector.recordError('failing-op', 100, 'Error', { retryCount: 3 });
159
-
160
- const content = fs.readFileSync(logFile, 'utf-8');
161
- expect(content).toContain('retryCount');
162
- });
163
- });
164
-
165
- describe('readRecent', () => {
166
- it('应该读取最近 N 小时的数据', () => {
167
- collector.recordOk('recent-op', 100);
168
-
169
- const traces = collector.readRecent(1);
170
- expect(traces.length).toBe(1);
171
- });
172
- });
173
-
174
- describe('readByOperation', () => {
175
- it('应该过滤特定操作', () => {
176
- collector.recordOk('op1', 100);
177
- collector.recordOk('op2', 200);
178
- collector.recordOk('op1', 150);
179
-
180
- const traces = collector.readByOperation('op1');
181
- expect(traces.length).toBe(2);
182
- });
183
- });
184
-
185
- describe('过滤条件', () => {
186
- it('应该按时间范围过滤', () => {
187
- const now = Date.now();
188
- collector.record({ operation: 'old', timestamp: now - 100000, duration: 100, result: 'ok' });
189
- collector.record({ operation: 'new', timestamp: now, duration: 100, result: 'ok' });
190
-
191
- const traces = collector.read({
192
- timeRange: { start: now - 50000, end: now + 1000 },
193
- });
194
-
195
- expect(traces.length).toBe(1);
196
- expect(traces[0]?.operation).toBe('new');
197
- });
198
-
199
- it('应该按结果类型过滤', () => {
200
- collector.recordOk('ok-op', 100);
201
- collector.recordError('err-op', 200, 'error');
202
-
203
- const traces = collector.read({ result: 'error' });
204
- expect(traces.length).toBe(1);
205
- expect(traces[0]?.operation).toBe('err-op');
206
- });
207
-
208
- it('应该按项目路径过滤', () => {
209
- collector.record({ operation: 'op1', timestamp: Date.now(), duration: 100, result: 'ok', projectPath: '/project1' });
210
- collector.record({ operation: 'op2', timestamp: Date.now(), duration: 100, result: 'ok', projectPath: '/project2' });
211
-
212
- const traces = collector.read({ projectPath: '/project1' });
213
- expect(traces.length).toBe(1);
214
- });
215
-
216
- it('应该按会话 ID 过滤', () => {
217
- collector.record({ operation: 'op1', timestamp: Date.now(), duration: 100, result: 'ok', sessionId: 'session-1' });
218
- collector.record({ operation: 'op2', timestamp: Date.now(), duration: 100, result: 'ok', sessionId: 'session-2' });
219
-
220
- const traces = collector.read({ sessionId: 'session-1' });
221
- expect(traces.length).toBe(1);
222
- });
223
-
224
- it('应该按任务 ID 过滤', () => {
225
- collector.record({ operation: 'op1', timestamp: Date.now(), duration: 100, result: 'ok', taskId: 'task-1' });
226
- collector.record({ operation: 'op2', timestamp: Date.now(), duration: 100, result: 'ok', taskId: 'task-2' });
227
-
228
- const traces = collector.read({ taskId: 'task-1' });
229
- expect(traces.length).toBe(1);
230
- });
231
-
232
- it('应该按角色 ID 过滤', () => {
233
- collector.record({ operation: 'op1', timestamp: Date.now(), duration: 100, result: 'ok', roleId: 'role-1' });
234
- collector.record({ operation: 'op2', timestamp: Date.now(), duration: 100, result: 'ok', roleId: 'role-2' });
235
-
236
- const traces = collector.read({ roleId: 'role-1' });
237
- expect(traces.length).toBe(1);
238
- });
239
- });
240
-
241
- describe('cleanupOldFiles', () => {
242
- it('应该清理旧备份文件', () => {
243
- // 创建一些备份文件(模拟滚动)
244
- const backupFile = logFile.replace('.log', '-2026-01-01.log');
245
- fs.writeFileSync(backupFile, 'old data');
246
-
247
- // 由于文件是新建的,需要修改 mtime
248
- // 简单验证函数运行不崩溃
249
- const deleted = collector.cleanupOldFiles(0);
250
- expect(deleted).toBeGreaterThanOrEqual(0);
251
-
252
- // 清理备份文件
253
- try { fs.unlinkSync(backupFile); } catch {}
254
- });
255
-
256
- it('不存在目录时应该返回 0', () => {
257
- // 创建新的 collector,使用临时目录
258
- const nonexistentDir = path.join(process.cwd(), 'temp-nonexistent-perf');
259
- const nonexistentLogFile = path.join(nonexistentDir, 'perf.log');
260
- const newCollector = new PerformanceCollector({ logFile: nonexistentLogFile });
261
-
262
- const deleted = newCollector.cleanupOldFiles(30);
263
- expect(deleted).toBe(0);
264
- });
265
- });
266
-
267
- describe('文件滚动', () => {
268
- it('应该检查文件大小', () => {
269
- // 创建大文件触发滚动检查
270
- collector.recordOk('test', 100);
271
-
272
- // 文件应该存在
273
- expect(fs.existsSync(logFile)).toBe(true);
274
- });
275
- });
276
- });
@@ -1,65 +0,0 @@
1
- /**
2
- * presets 测试
3
- */
4
-
5
- import { describe, it, expect } from '@jest/globals';
6
- import { STRICT_PRESET, STANDARD_PRESET, RELAXED_PRESET, getPreset } from '../presets/standard';
7
-
8
- describe('Presets', () => {
9
- describe('STRICT_PRESET', () => {
10
- it('应该启用所有约束', () => {
11
- expect(STRICT_PRESET.name).toBe('strict');
12
- expect(STRICT_PRESET.ironLaws).toBeNull();
13
- expect(STRICT_PRESET.guidelines).toBeNull();
14
- expect(STRICT_PRESET.prompts).toBeNull();
15
- });
16
- });
17
-
18
- describe('STANDARD_PRESET', () => {
19
- it('应该启用所有约束', () => {
20
- expect(STANDARD_PRESET.name).toBe('standard');
21
- expect(STANDARD_PRESET.ironLaws).toBeNull();
22
- expect(STANDARD_PRESET.guidelines).toBeNull();
23
- expect(STANDARD_PRESET.prompts).toBeNull();
24
- });
25
- });
26
-
27
- describe('RELAXED_PRESET', () => {
28
- it('应该只启用核心约束', () => {
29
- expect(RELAXED_PRESET.name).toBe('relaxed');
30
- expect(RELAXED_PRESET.ironLaws).not.toBeNull();
31
- expect(RELAXED_PRESET.guidelines).not.toBeNull();
32
- expect(RELAXED_PRESET.prompts).toEqual([]);
33
- });
34
-
35
- it('应该包含 no_completion_without_verification', () => {
36
- expect(RELAXED_PRESET.ironLaws).toContain('no_completion_without_verification');
37
- });
38
-
39
- it('应该包含 no_bypass_checkpoint', () => {
40
- expect(RELAXED_PRESET.guidelines).toContain('no_bypass_checkpoint');
41
- });
42
- });
43
-
44
- describe('getPreset', () => {
45
- it('应该返回 strict 预设', () => {
46
- const preset = getPreset('strict');
47
- expect(preset.name).toBe('strict');
48
- });
49
-
50
- it('应该返回 standard 预设', () => {
51
- const preset = getPreset('standard');
52
- expect(preset.name).toBe('standard');
53
- });
54
-
55
- it('应该返回 relaxed 预设', () => {
56
- const preset = getPreset('relaxed');
57
- expect(preset.name).toBe('relaxed');
58
- });
59
-
60
- it('未知预设应该返回 standard', () => {
61
- const preset = getPreset('unknown');
62
- expect(preset.name).toBe('standard');
63
- });
64
- });
65
- });
@@ -1,253 +0,0 @@
1
- /**
2
- * ConstraintInterceptor 测试
3
- */
4
-
5
- import { ConstraintInterceptor } from '../interceptor';
6
- import { constraintChecker } from '../checker';
7
- import type { ConstraintContext } from '../../../types/constraint';
8
- import type { EnforcementExecutor } from '../../../types/enforcement';
9
-
10
- // Mock constraintChecker
11
- jest.mock('../checker', () => ({
12
- constraintChecker: {
13
- getConstraints: jest.fn(),
14
- check: jest.fn().mockResolvedValue({ satisfied: true }),
15
- },
16
- }));
17
-
18
- const mockChecker = constraintChecker as jest.Mocked<typeof constraintChecker>;
19
-
20
- describe('ConstraintInterceptor', () => {
21
- let interceptor: ConstraintInterceptor;
22
-
23
- const mockCheck = jest.fn().mockResolvedValue({ satisfied: true });
24
-
25
- const mockIronLaw = {
26
- id: 'test_iron_law',
27
- kind: 'check' as const,
28
- rule: 'Test Iron Law',
29
- message: 'Test iron law message',
30
- level: 'iron_law' as const,
31
- trigger: 'code_implementation',
32
- enforcement: 'test-enforcement',
33
- check: mockCheck,
34
- };
35
-
36
- const mockGuideline = {
37
- id: 'test_guideline',
38
- kind: 'check' as const,
39
- rule: 'Test Guideline',
40
- message: 'Test guideline message',
41
- level: 'guideline' as const,
42
- trigger: 'code_implementation',
43
- enforcement: 'guideline-enforcement',
44
- check: mockCheck,
45
- };
46
-
47
- const mockContext: ConstraintContext = {
48
- operation: 'code_implementation',
49
- projectPath: '/test',
50
- };
51
-
52
- const mockExecutor: EnforcementExecutor = {
53
- execute: jest.fn(),
54
- };
55
-
56
- beforeEach(() => {
57
- jest.clearAllMocks();
58
- // Use the singleton instance
59
- interceptor = ConstraintInterceptor.getInstance();
60
- // Clear any previous state
61
- interceptor.clearSkips();
62
- interceptor.setEnabled(true);
63
-
64
- mockChecker.getConstraints.mockReturnValue({
65
- ironLaws: { test_iron_law: mockIronLaw },
66
- guidelines: { test_guideline: mockGuideline },
67
- prompts: {},
68
- });
69
- });
70
-
71
- describe('getInstance', () => {
72
- it('should return singleton instance', () => {
73
- const instance1 = ConstraintInterceptor.getInstance();
74
- const instance2 = ConstraintInterceptor.getInstance();
75
- expect(instance1).toBe(instance2);
76
- });
77
- });
78
-
79
- describe('register', () => {
80
- it('should register executor', () => {
81
- interceptor.register('test-enforcement', mockExecutor);
82
- expect(interceptor.hasExecutor('test-enforcement')).toBe(true);
83
- });
84
- });
85
-
86
- describe('registerBatch', () => {
87
- it('should register multiple executors', () => {
88
- interceptor.registerBatch([
89
- { enforcementId: 'exec1', executor: mockExecutor },
90
- { enforcementId: 'exec2', executor: mockExecutor },
91
- ]);
92
- expect(interceptor.hasExecutor('exec1')).toBe(true);
93
- expect(interceptor.hasExecutor('exec2')).toBe(true);
94
- });
95
- });
96
-
97
- describe('unregister', () => {
98
- it('should unregister executor', () => {
99
- interceptor.register('test-enforcement', mockExecutor);
100
- const result = interceptor.unregister('test-enforcement');
101
- expect(result).toBe(true);
102
- expect(interceptor.hasExecutor('test-enforcement')).toBe(false);
103
- });
104
-
105
- it('should return false if not exists', () => {
106
- const result = interceptor.unregister('nonexistent');
107
- expect(result).toBe(false);
108
- });
109
- });
110
-
111
- describe('getExecutor', () => {
112
- it('should return registered executor', () => {
113
- interceptor.register('test-enforcement', mockExecutor);
114
- const executor = interceptor.getExecutor('test-enforcement');
115
- expect(executor).toBe(mockExecutor);
116
- });
117
-
118
- it('should return undefined if not registered', () => {
119
- const executor = interceptor.getExecutor('nonexistent');
120
- expect(executor).toBeUndefined();
121
- });
122
- });
123
-
124
- describe('getRegistrations', () => {
125
- it('should return all registrations', () => {
126
- interceptor.unregister('test-enforcement'); // Clear any existing
127
- interceptor.register('test-enforcement', mockExecutor);
128
- const registrations = interceptor.getRegistrations();
129
- const found = registrations.find(r => r.id === 'test-enforcement');
130
- expect(found).toBeDefined();
131
- });
132
- });
133
-
134
- describe('setEnabled', () => {
135
- it('should disable interceptor', () => {
136
- interceptor.setEnabled(false);
137
- interceptor.register('test-enforcement', mockExecutor);
138
-
139
- const result = interceptor.intercept('code_implementation', mockContext);
140
- // When disabled, should pass without checking
141
- expect(result).resolves.toHaveProperty('passed', true);
142
- });
143
- });
144
-
145
- describe('skip', () => {
146
- it('should skip specified enforcements', async () => {
147
- interceptor.register('test-enforcement', mockExecutor);
148
- interceptor.skip(['test-enforcement']);
149
-
150
- const result = await interceptor.intercept('code_implementation', mockContext);
151
- expect(result.constraints.some(c => c.skipped)).toBe(true);
152
- });
153
- });
154
-
155
- describe('clearSkips', () => {
156
- it('should clear all skips', async () => {
157
- interceptor.register('test-enforcement', mockExecutor);
158
- interceptor.skip(['test-enforcement']);
159
- interceptor.clearSkips();
160
-
161
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: true });
162
- await interceptor.intercept('code_implementation', mockContext);
163
- expect(mockExecutor.execute).toHaveBeenCalled();
164
- });
165
- });
166
-
167
- describe('intercept', () => {
168
- it('should pass when all constraints satisfied', async () => {
169
- interceptor.register('test-enforcement', mockExecutor);
170
- interceptor.register('guideline-enforcement', mockExecutor);
171
-
172
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: true });
173
-
174
- const result = await interceptor.intercept('code_implementation', mockContext);
175
- expect(result.passed).toBe(true);
176
- expect(result.violations.length).toBe(0);
177
- });
178
-
179
- it('should fail on iron law violation', async () => {
180
- interceptor.register('test-enforcement', mockExecutor);
181
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: false });
182
-
183
- await expect(interceptor.intercept('code_implementation', mockContext)).rejects.toThrow();
184
- });
185
-
186
- it('should record guideline violation without throwing', async () => {
187
- interceptor.register('test-enforcement', mockExecutor);
188
- interceptor.register('guideline-enforcement', mockExecutor);
189
-
190
- (mockExecutor.execute as jest.Mock)
191
- .mockResolvedValueOnce({ passed: true }) // iron law passes
192
- .mockResolvedValueOnce({ passed: false }); // guideline fails
193
-
194
- const result = await interceptor.intercept('code_implementation', mockContext);
195
- expect(result.passed).toBe(true); // guidelines don't block
196
- expect(result.violations.length).toBe(1);
197
- });
198
-
199
- it('should handle missing executor', async () => {
200
- // No constraints at all
201
- mockChecker.getConstraints.mockReturnValue({
202
- ironLaws: {},
203
- guidelines: {},
204
- prompts: {},
205
- });
206
-
207
- const result = await interceptor.intercept('code_implementation', mockContext);
208
- expect(result.passed).toBe(true);
209
- expect(result.constraints.length).toBe(0);
210
- });
211
-
212
- it('should handle executor error for iron law', async () => {
213
- interceptor.register('test-enforcement', mockExecutor);
214
- (mockExecutor.execute as jest.Mock).mockRejectedValue(new Error('Executor error'));
215
-
216
- await expect(interceptor.intercept('code_implementation', mockContext)).rejects.toThrow();
217
- });
218
- });
219
-
220
- describe('claim', () => {
221
- it('should pass when constraints satisfied', async () => {
222
- interceptor.register('test-enforcement', mockExecutor);
223
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: true });
224
-
225
- await expect(interceptor.claim('code_implementation', mockContext)).resolves.not.toThrow();
226
- });
227
-
228
- it('should throw on violation', async () => {
229
- interceptor.register('test-enforcement', mockExecutor);
230
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: false });
231
-
232
- await expect(interceptor.claim('code_implementation', mockContext)).rejects.toThrow();
233
- });
234
- });
235
-
236
- describe('canProceed', () => {
237
- it('should return true when passed', async () => {
238
- interceptor.register('test-enforcement', mockExecutor);
239
- (mockExecutor.execute as jest.Mock).mockResolvedValue({ passed: true });
240
-
241
- const result = await interceptor.canProceed('code_implementation', mockContext);
242
- expect(result).toBe(true);
243
- });
244
-
245
- it('should return false on error', async () => {
246
- interceptor.register('test-enforcement', mockExecutor);
247
- (mockExecutor.execute as jest.Mock).mockRejectedValue(new Error('Error'));
248
-
249
- const result = await interceptor.canProceed('code_implementation', mockContext);
250
- expect(result).toBe(false);
251
- });
252
- });
253
- });